信號
信號(signal)就是可知某個進程發生了某個事件的通知,有時也稱爲軟件中斷(software interruption)。
信號通常是異步發生的。
信號可以:
*由一個進程發給另一個進程(或自身)
*由內核發給某個進程
每個信號都有一個與之關聯的處置(disposition),也稱爲行爲(action)。
通過sigaction函數來設定一個信號的處置,有三種選擇:
(1)信號發生時調用信號處理函數(signal handler),即捕獲(catching)信號,
其中,SIGKILL,SIGSTOP兩個信號無法被捕捉。
函數原型:void handler(int signo);
(2)通過設置信號處理辦法爲SIG_ING來忽略信號,
其中,SIGKILL,SIGSTOP無法被忽略。
(3)通過設置信號處理辦法爲SIG_DFL來設置信號的默認處置方法,
默認處置通常是早收到信號後終止進程,個別信號的默認處置是忽略。
signal函數
建立信號處置的POSIX方法就是調用sigaction函數。簡單的方法是用signal函數,它的第一個參數是信號名,第二個參數是指向函數的指針或爲常值SIG_DFL或SIG_IGN。
由於歷史原因,signal在各種平臺上的實現可能會不盡相同,而POSIX明確規定調用sigaction函數的語義,但sigaction函數調用往往比較複雜,解決方法是用sigaction實現自己的signal函數,signal函數原型:
void (*signal(int signo, void (*handle)(int)))(int);
其中signal接受兩個參數,一個int型的信號編碼,另一個處理信號的函數指針,然後返回一個之前定義的處理信號的函數的指針,處理函數接受一個int型參數,返回void,這樣看起來挺麻煩的,簡單點可以這樣定義:
typdef void (SIG_HANDLE)(int);
SIG_HANDLE signal(int, SIG_HANDLE );
好了,知道了signal的基本語義了,現在可以用sigaction實現它了,代碼如下:
#include <signal.h>
/*
* 用sigaction實現signal
*/
typedef void (SIG_PROC)(int);
SIG_PROC *_signal(int signo, SIG_PROC *sig_proc)
{
struct sigaction act;
struct sigaction oact;
act.sa_handler = sig_proc;
// 設置信號處理函數的信號掩碼:信號處理函數調用期間,除屏蔽本信號外,不阻塞其他信號,
// 信號處理函數執行完畢後,信號屏蔽字恢復到之前的值
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
// 除了SIGALRM以外的其他信號,如果被中斷都將嘗試重新啓動(linux下)
if (signo == SIGALRM)
{
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
}
else
{
#ifdef SA_RESTART
//如果設置了restart,內核將重啓被中斷的系統調用,系統調用不會返回-1
act.sa_flags |= SA_RESTART;
#endif
}
if (sigaction(signo, &act, &oact) < 0)
{
return SIG_ERR;
}
return oact.sa_handler;
}