Linux進程通信——信號(一)

原理

對于 Linux來說,實際信號是軟中斷,許多重要的程序都需要處理信號。
信號,為 Linux 提供了一種處理異步事件的方法。比如,終端用戶輸入了ctrl+c來中斷程序,會通過信號機制停止一個程序。

概述

信號的名字和編號

每個信號都有一個名字和編號,這些名字都以“SIG”開頭,例如“SIGUP(掛起) ”、“SIGINT(中斷)、SIGQUIT(退出)”等等。
信號定義在signal.h頭文件中,信號名都定義為正整數
具體的信號名稱可以 使用kill -l查看信號的名字以及序號
信號是從1開始編號的,不存在0號信號。kill對于信號0有特殊的應用。

信號的處理

信號的處理方式有三種,分別是忽略、捕捉和默認動作

忽略信號

大多數信號可以使用這個方式來處理,但是有兩種信號不能被忽略(分別是 SIGKILLSIGSTOP)。因為他們向內核和超級用戶提供了進程終止和停止的可靠方法,如果忽略了,那么這個進程就變成了沒人能管理的的進程,顯然是內核設計者不希望看到的場景。

系統自帶的忽略宏函數

 signal(SIGINT,SIG_IGN);//將SIGINT信號(ctrl+C、2)忽略

捕捉信號

需要告訴內核,用戶希望如何處理某一種信號,說白了就是寫一個信號處理函數,然后將這個函數告訴內核。當該信號產生時,由內核來調用用戶自定義的函數,以此來實現某種信號的處理。(?在main函數外定義一個函數,用signal函數中的參數調用該函數并執行函數中的功能)

系統默認動作

對于每個信號來說,系統都對應由默認的處理動作,當發生了該信號,系統會自動執行。不過,對系統來說,大部分的處理方式都比較粗暴,就是直接殺死該進程。
具體的信號默認動作可以使用man 7 signal來查看系統的具體定義。在此,我就不詳細展開了,需要查看的,可以自行查看。也可以參考 《UNIX 環境高級編程(第三部)》的 P251——P256中間對于每個信號有詳細的說明。

例子如下:

其實對于常用的 kill 命令就是一個發送信號的工具,kill 9 PID 來殺死進程。比如,我在后臺運行了一個 a.out?工具,通過 ps 命令可以查看他的 PID,通過 kill 9來發送了一個終止進程的信號來結束了 a.out?進程。如果查看信號編號和名稱,可以發現9對應的是 SIGKILL,正是殺死該進程的信號。而以下的執行過程實際也就是執行了9號信號的默認動作——殺死進程。

kill -9 進程PID
kill -SIGKILL 進程PID

可見,兩者的執行結果相同。說明kill命令是發送信號的工具

signal函數

功能

設置某一信號的對應動作

頭文件

#include <signal.h>

原型

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

函數解讀

第一行是真實處理信號的函數:中斷函數的原型中,有一個參數是 int 類型,顯然也是信號產生的類型,方便使用一個函數來處理多個信號,即注冊函數的第二個參數可以調用信號處理函數并執行其中的功能。

第二行是信號處理注冊的函數:

signum信號的編號,如SIGKILL的編號是9
handler中斷函數的指針,寫入后可以調用編寫的真實處理信號函數并執行功能

signal()會依參數signum指定的信號編號來設置該信號的處理函數。當指定的信號到達時就會跳轉到參數handler指定的函數執行

返回值

成功則返回先前的信號處理函數指針,如果有錯誤則返回SIG_ERR(-1)。

代碼示例

信號處理函數的注冊

signal1.c

#include <stdio.h>
#include <signal.h>void handler(int signum)
{printf("get signum is %d\n",signum);printf("not quit\n");switch(signum){case 2:printf("SIGINT\n");break;case 9:printf("SIGKILL\n");break;case 10:printf("SIGUSR1\n");break;}
}int main()
{signal(SIGINT,handler);signal(SIGUSR1,handler);while(1);return 0;
}

代碼編譯后查看運行a.out工具,通過ps查看其編號

運用kill指令分別對信號進行處理

注:第一種按下crtl+c執行結果相同。

可見調用signal函數后匹配的正確編號后會執行handler中的功能(將函數編號打印出來)。第三個與前兩個結果不一樣是因為SIGKILL指令無法被忽略,這里的kill -9發出的是指令,由于代碼為死循環,若SIGKILL被忽視,則會導致代碼無法終止循環,所以一旦SIGKILL指令發出,程序立刻停止(被殺死)。

發送信號處理函數

signal2.c

#include <stdio.h>
#include <signal.h>int main(int argc,char **argv)//由于需要此代碼發送指令另一部分代碼才會執行,所以需要進行傳參,參數為kill參數,格式為./a.out pid signum
{int signum;int pid;signum = atoi(argv[1]);pid = atoi(argv[2]);kill(pid,signum);//調用kill函數,將信號處理編號和工具的pid值輸入即可printf("send signal success\n");return 0;
}

?先編譯signal1.c(上一模塊的代碼)并運行

調用ps指令查看該程序的信號值

編譯運行signal2.c中的代碼傳參即可運行signal1.c代碼中的功能

將signum與pid輸入后即可實現signal1.c中的功能,實現信號捕捉處理。

功能與signal2.c一樣的代碼:

#include <stdio.h>
#include <signal.h>int main(int argc,char **argv)
{int signum;int pid;char cmd[128] = {0};signum = atoi(argv[1]);pid = atoi(argv[2]);sprintf(cmd,"kill -%d %d",pid,signum);//cmd的指令格式為“”里的格式,即調用kill指令system(cmd);//調用cmd指令printf("send signal success\n");return 0;
}

注:
1、atoi (表示 ascii to integer)是把字符串轉換成整型數的一個函數
2、sprintf指的是字符串格式化命令,函數原型為

 int sprintf(char *string, char *format [,argument,…]);

主要功能是把格式化的數據寫入某個字符串中,即發送格式化輸出到 string 所指向的字符串

信號忽略函數的補充

代碼展示

#include<stdio.h>
#include <signal.h>
void handler(int signum)
{printf("get signum=%d\n",signum);switch(signum){case 2:printf("SIGINT\n");break;case 10:printf("SIGUSR1\n");break;}
}
int main()
{signal(SIGINT,SIG_IGN);//將SIGINT信號(ctrl+C、2)忽略signal(SIGUSR1,SIG_IGN);//將SIGUSR1信號(10)忽略while(1);return 0;
}

可見crtl+c和kill -10和kill -2都被忽略了,只有kill -9才能使該程序終止,印證的信號處理中的忽略部分不能忽略SIGKILL。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/165411.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/165411.shtml
英文地址,請注明出處:http://en.pswp.cn/news/165411.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Docker】從零開始:8.Docker命令:Commit提交命令

【Docker】從零開始&#xff1a;8.Docker命令:Commit命令 基本概念鏡像鏡像分層什么是鏡像分層為什么 Docker 鏡像要采用這種分層結構 本章要點commit 命令命令格式docker commit 操作參數實例演示1.下載一個新的ubuntu鏡像2.運行容器3.查看并安裝vim4.退出容器5提交自己的鏡像…

【數據結構/C++】線性表_雙鏈表基本操作

#include <iostream> using namespace std; typedef int ElemType; // 3. 雙鏈表 typedef struct DNode {ElemType data;struct DNode *prior, *next; } DNode, *DLinkList; // 初始化帶頭結點 bool InitDNodeList(DLinkList &L) {L (DNode *)malloc(sizeof(DNode))…

成為AI產品經理——模型評估概述

目錄 一、模型宣講和評估的原因 二、模型宣講 三、模型評估 1. 重要特征 ① 特征來源 ②特征意義 2.選擇測試樣本 3.模型性能和穩定性 一、模型宣講和評估的原因 劉海豐老師提到他們在做一個金融AI產品未注重模型指標&#xff0c;過于注重業務指標&#xff0c;導致產生…

解決:ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘

解決&#xff1a;ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘ 背景 在使用之前的代碼時&#xff0c;報錯&#xff1a; from keras.optimizers import Adam ImportError: cannot import name ‘Adam’ 報錯問題 from keras.optimizers import Adam I…

2023年亞太數學建模大賽--A題(水果采摘機器人的圖像識別功能)

中國是世界上最大的蘋果生產國&#xff0c;年產量約為 3500 萬噸。同時&#xff0c;中國也是世界上最大的蘋果出口國&#xff0c;世界上每兩個蘋果中就有一個出口到國。世界上每兩個蘋果中就有一個來自中國&#xff0c;中國出口的蘋果占全球出口量的六分之一以上。來自中國。中…

Vue CLI的介紹【vue利器之一】

文章目錄 前言Vue CLI 介紹CLICLI 服務CLI 插件后言 前言 hello world歡迎來到前端的新世界 &#x1f61c;當前文章系列專欄&#xff1a;vue.js &#x1f431;?&#x1f453;博主在前端領域還有很多知識和技術需要掌握&#xff0c;正在不斷努力填補技術短板。(如果出現錯誤&am…

【Java 進階篇】Redis持久化之RDB:數據的安全守護者

Redis&#xff0c;作為一款高性能的鍵值存儲系統&#xff0c;支持多種持久化方式&#xff0c;其中RDB&#xff08;Redis DataBase&#xff09;是其最常用的一種。RDB可以將當前時刻的數據快照保存到磁盤&#xff0c;以便在Redis重啟時快速恢復數據。本文將深入探討RDB的原理、配…

飛書智能伙伴之 AI 數智參謀:先進團隊,北極星指標也要遙遙領先

11 月 22 日&#xff0c;飛書在 2023 秋季飛書未來無限大會上正式發布了飛書智能伙伴。作為首批生態伙伴&#xff0c;基于 Kyligence 智能一站式指標平臺實現的 AI 數智參謀也正式亮相。這是繼 11 月 21 日 Kyligence 產品發布會后&#xff0c;Kyligence 在數據驅動決策智能領域…

第十五屆藍橋杯(Web 應用開發)模擬賽 1 期-大學組(詳細分析解答)

目錄 1.動態的Tab欄 1.1 題目要求 1.2 題目分析 1.3 源代碼 2.地球環游 2.1 題目要求 2.2 題目分析 2.3 源代碼 3.迷惑的this 3.1 題目要求 3.2 題目分析 3.3 源代碼 4.魔法失靈了 4.1 題目要求 4.2 題目分析 4.3 源代碼 5.燃燒你的卡路里 5.1 題目要求 5.2…

第十七章:數據庫操作

數據庫基礎 SQL語言 1、select 語句 select 語句用于從數據中檢索數據。語法如下&#xff1a; SELECT 搜選字段列表 FROM 數據表名 WHERE 條件表達式 GROUP BY 字段名 HAVING 條件表達式(指定分組的條件) ORDER BY 字段名[ASC|DESC] 2、insert 語句 insert 語句用于向表中插入…

重新使用hbase前

啟動關閉Hadoop和HBase的順序一定是&#xff1a; 啟動Hadoop—>啟動HBase—>關閉HBase—>關閉Hadoop 1.掛載共享文件夾到掛載點 sudo mount -t vboxsf virtualmachineShare /mnt/shared2.進入hadoop目錄下啟動hadoop cd /usr/local/hadoop/ ./sbin/start-all.sh …

【UE5】五大基類及其使用

UObject UObject表示對象&#xff0c;準確來說&#xff0c;虛幻引擎中的對象基礎類為UObject UObject提供了以下功能&#xff1a; 垃圾收集&#xff08;Garbage collection&#xff09;引用自動更新&#xff08;Reference updating&#xff09;反射&#xff08;Reflection&am…

火電廠電氣部分設計

摘要 本文首先根據任務書上所給系統與線路及所有負荷的參數&#xff0c;分析負荷發展趨勢。從負荷增長方面闡明了建站的必要性&#xff0c;然后通過對擬建變電站的概括以及出線方向來考慮&#xff0c;并通過對負荷資料的分析&#xff0c;安全&#xff0c;經濟及可靠性方面考慮…

計算機基礎知識57

前后端數據傳輸的編碼格式(contentType) # 我們只研究post請求方式的編碼格式&#xff1a; get請求方式沒有編碼格式-- index?useranme&password get請求方式沒有請求體&#xff0c;參數直接在url地址的后面拼接著 # 有哪些方式可以提交post請求&#xff1a;f…

構建個性化預約服務:預約上門服務系統源碼解讀與實戰

隨著社會的發展&#xff0c;預約上門服務系統在滿足用戶需求、提升服務效率方面發揮著越來越重要的作用。在本文中&#xff0c;我們將深入研究預約上門服務系統的源碼&#xff0c;通過實際的技術代碼示例&#xff0c;揭示系統內部的關鍵機制&#xff0c;以及如何在實際項目中應…

qml動畫過渡Transition

文章目錄 基本概念使用 `Transition`示例動畫過渡高級用法示例:復雜動畫過渡解釋進階用法在 QML 中,Transition 元素用于定義狀態之間過渡時的動畫。這是 QML 強大的狀態機制的一部分,允許開發者創建平滑且吸引人的用戶界面交互。使用 Transition,您可以定義當元素從一個狀…

深入了解接口測試:方法、工具和關鍵考慮因素(一)

接口測試是軟件測試中的一項重要工作&#xff0c;它涉及到系統與系統之間的交互點。接口可以是外部接口&#xff0c;也可以是內部接口&#xff0c;包括上層服務與下層服務接口以及同級接口。在接口測試中&#xff0c;我們需要確保接口能夠按照預期的方式進行通信和交互&#xf…

【攻防世界-misc】can_has_stdio?

1.用記事本打開文件是這樣子的&#xff0c; 這是一段BF&#xff08;Brainfuck&#xff09;編程語言代碼&#xff0c;屬于一種極簡化的編程語言&#xff0c;用于演示計算機程序設計概念。這段代碼包含了一些操作符&#xff0c;如">"表示指針向右移動&#xff0c;&q…

【C++破局】泛型編程|函數模板|類模板

?作者主頁 &#x1f4da;lovewold少個r博客主頁 ??本文重點&#xff1a;c模板初階知識點講解 &#x1f449;【C-C入門系列專欄】&#xff1a;博客文章專欄傳送門 &#x1f604;每日一言&#xff1a;花有重開日&#xff0c;人無再少年 目錄 前言 泛型編程 函數模板 函數模…

用Java實現簡易的圖書管理系統(超詳細)

目錄 1.設計背景 2.設計思路 3.模塊展示及代碼演示 3.1 Book類的實現 3.2 BookList類的實現(書架) 3.3 異常類的實現(OperationException) 3.4 用戶類的實現 3.5 操作接口的實現(定義規范) 3.6 操作類的具體實現 3.6.1 增加操作 3.6.2 查找操作 3.6.3 刪除操作 3.6…