Linux訊號機制(一) 訊號

2021-10-02 04:46:15 字數 3329 閱讀 2329

在linux中訊號是程序間通訊的重要手段,訊號可以通知乙個程序發生了什麼,訊號的產生是突發事件,所以也被稱為「軟體中斷」

通過檢視檔案了解到訊號是巨集定義的常量,以sig開頭

值得注意的是:不存在值為0的訊號,值為0的訊號稱為空訊號,kill函式對值為0的訊號有特殊的應用

當乙個程序收到乙個訊號,有三種處理方式:[1]

訊號名訊號值

訊號含義

系統預設動作

sighup

1終端斷開訊號,遠端登入時,如果終端介面檢測到連線斷開時,

則將該訊號傳送給與該終端相關的控制程序

終止程序

sigint

2ctrl+c觸發該訊號

終止程序

sigquit

3ctrl+\觸發該訊號

終止程序 + core轉儲

sigkill

9殺死任意程序的可靠方法,不能被忽略和捕獲

終止程序

sigusr1

10使用者定義訊號1,可用於應用程式

終止程序

sigse**

11訪問無效記憶體會觸發該訊號

終止程序 + core轉儲

sigusr2

12使用者定義訊號2,同sigusr1

終止程序

sigpipe

13寫入無人讀取的管道時會觸發該訊號,網路程式設計時要處理該訊號

終止程序

sigalrm

14超時訊號,呼叫alarm(),超時後會收到該訊號

終止程序

sigterm

15kill(1)命令預設傳送的訊號

終止程序

sigchld

17子程序狀態改變,子程序終止或者停止時會向父程序傳送該訊號

忽略sigcont

18使暫停程序繼續執行,如果收到該訊號的程序處於停止狀態,

則程序繼續執行,不過變為了後台執行。否則忽略該訊號

繼續/忽略

sigstop

19停止訊號,不能**獲和忽略

暫停程序

sigtstp

20終端停止訊號,可以**獲和忽略,ctrl+z觸發該訊號

暫停程序

之前對kill命令的認識是,用來殺死乙個程序(終止程序)

kill pid
kill命令的實質是給程序傳送乙個訊號(預設傳送sigterm終止訊號),如果程序沒有對該訊號的處理程式,則執行預設處理動作–終止程序

kill命令可以給程序傳送多種訊號

kill -n pid
n表示訊號值,比如:kill -1 10000,會向pid = 10000的程序傳送乙個sighup訊號,如果沒有對sighup訊號的處理的話,執行預設處理動作,將終止程序

signal()可以給指定訊號註冊乙個訊號處理動作,函式原型如下:[2]

#include typedef void(*sighandler_t)(int);

/* * @param signum:指定訊號

* @param handler:訊號處理動作

*/sighandler_t signal(int signum, sighandler_t handler);

示例**

#include // printf

#include // sleep

#include // signal

int main()

while(1)

return 0;

}

**編譯執行後,鍵盤按ctrl+c無法終止程式執行

sig_ign和sig_err都是中定義的常量

#define sig_err (void (*) ())-1

#define sig_ign (void (*) ())1

#include // printf

#include // sleep

#include // signal

void sig_usr(int sig)

else if(sig == sigusr2)

}int main()

else if(signal(sigusr2,sig_usr) == sig_err)

while(1)

return 0;

}

**編譯執行後,用kill命令傳送sigusr1和sigusr2訊號會觸發執行sig_usr(),處理流程如下圖所示:

在沒有訊號來之前,程式執行在使用者態,訊號來之後,程式會切換到核心態判斷當前程序對該訊號的處理動作是什麼,這裡指定了sig_usr()作為訊號處理動作,所以返回到使用者態執行sig_usr(),執行結束之後還是要返回到核心態做一些工作,最後返回使用者態繼續執行

訊號處理函式是不能隨意寫的,稍微修改上面程式如下:

#include // printf

#include // sleep

#include // signal

int gnum;

void set_num(int num)

void sig_usr(int sig)

else if(sig == sigusr2)

}int main()

else if(signal(sigusr2,sig_usr) == sig_err)

while(1)

return 0;

}

在main函式和訊號處理函式中都去修改全域性變數gnum的值,由於訊號處理函式是隨時可能被呼叫的,printf在列印是gnum不是確定的,根據這個例子就能引出可重入函式的概念

可重入函式是指:在訊號處理函式中呼叫該函式是安全的,不會出現不確定的情況

所以上面**中的set_num()不是乙個可重入的函式,還有像malloc()、printf()這些常用的函式也不是可重入函式

由此也可以總結編寫訊號處理函式的注意事項:

訊號處理函式中只做簡單操作,盡量不要呼叫系統函式

如果非要呼叫系統函式,則要保證系統函式是可重入的

可重入的系統函式可能會對errno這個全域性變數做修改,此時應在訊號處理函式開始對errno進行備份,在末尾在進行還原

Linux 信 號 機 制

前面介紹了訊號的基本概念,在這一節中,我們將介紹核心如何實現訊號機制。即核心如何向乙個程序傳送訊號 程序如何接收乙個訊號 程序怎樣控制自己對訊號的反應 核心在什麼時機處理和怎樣處理程序收到的訊號。還要介紹一下setjmp和longjmp在訊號中起到的作用。1 核心對訊號的基本處理方法 核心給乙個程序...

linux 訊號機制

本文旨在弄懂linux中的訊號工作原理 kill l 命令可以檢視linux下所有訊號 2.1 使用者在終端按下某些鍵時,終端驅動程式會傳送訊號給前台程序 例如ctrl c產生sigint訊號,ctrl 產生sigquit訊號,ctrl z產生sigtstp訊號 2.2 硬體異常產生訊號,這些條件由...

LINUX訊號機制

在電腦科學中,訊號是unix 類unix以及其他posix相容的作業系統中程序間通訊的一種有限制的方式。它是一種非同步的通知機制,用來提醒程序乙個事件已經發生。當乙個訊號傳送給乙個程序,作業系統中斷了程序正常的控制流程,此時,任何非原子操作都將被中斷。如果程序定義了訊號的處理函式,那麼它將被執行,否...