聯系我們 - 廣告服務 - 聯系電話:
您的當前位置: > 關注 > > 正文

環球動態:【進程通信】Signal信號 信號的來源是哪?

來源:CSDN 時間:2022-12-12 08:32:37

信號(signal)

軟中斷信號(signal,又簡稱為信號)是Linux下用來在進程間傳遞消息的方式之一,也是進程間唯一的異步通信方式。從命名中可以看出信號的實質很像中斷。進程間可以通過調用kill庫函數發送軟中斷信號,Linux內核也可能給進程發送信號,用以告知該進程發生了某個異步事件。

注意,信號只用來告知進程發生了某個異步事件,并不用來傳遞數據。進程收到信號后會有三種處理方式:


(資料圖片)

忽略,不做任何處理執行預先設置的處理函數(就像中斷服務程序一樣)采用系統的默認操作,大部分是終止進程

信號的來源

用戶

一般是鍵盤的輸入會作為信號發送給進程,比如:Ctrl + C發送SIGINT信號給進程,默認動作為終止進程;Ctrl + \發送SIGQUIT信號給進程,默認動作為終止進程并進行內核映像轉儲(core dump)

內核

當進程執行出錯時,內核給進程發送一個對應信號,例如:非法內存引用、浮點數溢出、執行非法指令

進程

C++的kill庫函數用于進程間發送信號

信號的類型

信號名信號值默認處理動作發出信號的原因

SIGINT2終止進程鍵盤中斷Ctrl+c

SIGQUIT3終止進程并進行內核映像轉儲鍵盤的退出鍵被按下

SIGKILL9終止進程,并且不能被捕獲、忽略采用kill -9 進程編號 強制殺死程序。

SIGSEGV11終止進程并進行內核映像轉儲無效的內存引用

SIGTERM15終止進程采用“kill 進程編號”或“killall 程序名”通知程序。

SIGCHLD20,17,18忽略此信號子進程結束信號

PS:

內核映像轉儲(core dump),內核映像轉儲是指將進程數據在內存的映像和進程在內核結構中的部分內容以一定格式轉儲到文件系統,并且進程退出執行,這樣做的好處是為程序員 提供了方便,使得他們可以得到進程當時執行時的數據值,允許他們確定轉儲的原因,并且可以調試他們的程序。

信號的捕獲處理

#includesighandler_t signal(int signum, sighandler_t handler)//signum 表示信號的編號    //handler 表示信號的處理方式,有三種:    1. SIG_IGN:忽略改信號,不作為    2. SIG_DFL:恢復該信號的默認處理方法    3. 自定義處理函數,注意函數參數為 (int signum)

信號的發送

int kill(pid_t pid, int sig)//pid 目標進程號,有三種情況:    1. pid>0 將信號sig傳給號為pid的進程    2. pid=0 將信號sig傳給同進程組的所有進程(包括自己),常用于父進程給子進程發送信號    3. pid=-1 將信號廣播到系統內所有進程,例如系統關機時向所有登錄窗口廣播關機信息    //sig 被發送的信號編號

信號的應用

屏蔽信號

通常為了程序不被干擾,程序開頭通常會屏蔽所有信號,然后再用signal函數對關心的信號設置相應的處理方式。

for(int i=0; i<100; i++) signal(i, SIG_IGN);

搞點好玩的

改變信號 SIGINT和 SIGTERM的捕獲處理,設計一個 ctrl+C和 kill都殺不掉的進程:

#include#include#includevoid func(int sig){if (sig == SIGINT)        printf("\b\b殺不死,哈哈哈哈。\n");    else if (sig == SIGTERM)        printf("還是殺不死,哈哈哈哈。\n");}int main(){for (int ii = 0; ii < 100; ii++)        signal(ii, SIG_IGN); // 屏蔽全部的信號    signal(SIGINT, func);    signal(SIGTERM, func); // 設置SIGINT和SIGTERM的處理函數    while (1);}

效果:

使用Ctrl+C嘗試關掉進程:

用 ps -ef | grep signal找到其進程號,嘗試用 kill 直接干掉:

可以看見,kill + 進程號或 killall + 進程名對它都無效,那改怎么殺死這個進程呢?如圖,用 kill -9 進程號:

因為kill -9 進程號發送的信號是 SIGKILL,這個信號無法被捕獲或忽略,能夠快準狠殺掉進程

使系統休眠

這個是我嘗試用 kill() 函數向系統所有進程發送 SIGKILL 信號后發現的,當然是在虛擬機上,我可不敢在主機上這樣搞:

#include#includeint main(){kill(-1, SIGKILL);}

效果是虛擬機進入休眠,輸入密碼后能再進入,原以為會直接關機呢

責任編輯:

標簽:

相關推薦:

精彩放送:

新聞聚焦
Top 岛国精品在线