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