訊號是linux中的一個重要概念,早期的Linux使用系統調用 signal 來安裝訊號
#include <signal.h>
void (*signal(int signum, void (*handler))(int)))(int);
該函數有兩個參數, signum指定要安裝的訊號, handler指定訊號的處理函數.
該函數的傳回值是一個函數指標, 指向上次安裝的handler
經典安裝方式:
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
signal(SIGINT, sig_handler);
}
先獲得上次的handler, 如果不是忽略訊號, 就安裝此訊號的handler
由於訊號被交付後, 系統自動的重設handler為預設動作, 為了使訊號在handler處理期間, 仍能對後繼訊號做出反應, 往往在handler的第一條語句再次調用signal
sig_handler(ing signum)
{
/* 重新安裝訊號 */
signal(signum, sig_handler);
......
}
我們知道在程式的任意執行點上, 訊號隨時可能發生, 如果訊號在sig_handler重新安裝訊號之前產生, 這次訊號就會執行預設動作, 而不是sig_handler. 這種問題是不可預料的. 這兩點構成了訊號的基本使用方式。
注意:Linux訊號機制基本上是從Unix系統中繼承過來的。早期Unix系統中的訊號機制比較簡單和原始,後來在實踐中暴露出一些問題,因此,把那些建立在早期機制上的訊號叫做"不可靠訊號",訊號值小於SIGRTMIN(Red hat 7.2中,SIGRTMIN=32,SIGRTMAX=63)的訊號都是不可靠訊號。這就是"不可靠訊號"的來源。它的主要問題是:進程每次處理訊號後,就將對訊號的響應設定為預設動作。在某些情況下,將導致對訊號的錯誤處理;因此,使用者如果不希望這樣的操作,那麼就要在訊號處理函數結尾再一次調用signal(),重新安裝該訊號。 kill -l查看所有可用的訊號
可靠訊號與不可靠訊號, 即時訊號與非即時訊號
可靠訊號就是即時訊號, 那些從UNIX系統繼承過來的訊號都是非可靠訊號, 表現在訊號不支援排隊,訊號可能會丟失, 比如發送多次相同的訊號, 進程只能收到一次. 訊號值小於SIGRTMIN的都是非可靠訊號.
非可靠訊號就是非即時訊號, 後來, Linux改進了訊號機制, 增加了32種新的訊號, 這些訊號都是可靠訊號, 表現在訊號支援排隊, 不會丟失, 發多少次, 就可以收到多少次. 訊號值位於 [SIGRTMIN, SIGRTMAX] 區間的都是可靠訊號.