1.信号特性:
簡單但不可靠,不能攜帶大量資訊,特定條件才觸發。
包括軟體中斷和硬體中斷。
軟體中斷如:調用abort、raise,alarm,setitimer等函數觸發的中斷
硬體中斷如:除0導緻的SIGFPE(浮點數例外),非法通路内容導緻的SIGSEGV(段錯誤),非法内容對齊等導緻的總線錯誤(SIGBUS) 等等
2.信号三要素:
1)編号:信号編号範圍是1~64。1~31為正常信号編号。34-64為實時信号。
2)事件:同時每個編号對應一個觸發事件。如1->SIGHUP,2->SIGINT,3->SIGQUIT,... man 7 signal 可檢視全部信号。
常見對應事件:Ctr+c 産生SIGINT(2),Ctrl+\ 産生SIGQUIT(3),Ctrl+z 産生SIGTSTP(20),
除0操作 産生SIGFPE(8)浮點數例外,非法通路記憶體 産生SIGSEGV(11)段錯誤,非法記憶體對齊等 産生SIGBUS(7)總線錯誤
3)預設動作:包括 Term終止程序,Ign忽悠,Core終止程序并生成Core檔案,Stop暫停程序,Cont繼續進行。
注意:SIGKILL(9)和SIGSTOP(19)信号不允許被屏蔽、忽略、捕捉等,隻能執行預設動作。SIGKILL預設終止程序,SIGSTOP預設暫停程序。
3.常見信号産生函數
kill(pid,sig)函數:發送sig信号。pid>0給指定程序 發送sig信号,pid=0給同組程序 發送sig信号,pid<-1給指定程序組 發送sig信号,pid=-1給所有程序 發送sig信号。
raise(sig) 函數:給目前程序發送sig信号。
abort() 函數:給目前程序發送SIGABRT信号。
alarm(sec) 函數:sec大于0時表示sec秒後給目前程序發送SIGALRM信号。sec=0表示取消定時器。每個程序隻有唯一一個定時器。
setitimer() 函數:周期定時器,which可選:ITIMER_REAL(自然定時,産生SIGALRM信号)、ITIMER_VIRTUAL(虛拟使用者空間計時,産生SIGVTALRM信号)、ITIMER_PROF(運作時計時,産生SIGPROF信号)
4.信号集
未決信号集:産生了但還沒決定處理的待處理信号集合。未決就是沒決定的意思嘛。
阻塞信号集:一般稱為信号屏蔽字mask。用來告訴核心屏蔽哪些信号,也就是說告訴核心哪些信号屏蔽掉不處理。
核心是通過讀取未決信号集來判斷信号是否應該被處理的,信号屏蔽字mask可以影響未決信号集合。我們可以通過程式修改mask的值達到屏蔽指定信号的目的。
簡單了解:就是所有未處理的信号,經過信号屏蔽字篩選後,剩下的就是未決信号集.
5.常見信号集操作函數
sigset_t:信号集類型,是一個unsigned long類型。沒錯,是一個基本資料類型,但表示一個信号集合,說明是按位操作。
sigemptyset(sigset_t *set) 函數:将set集合按位清空為0
sigfillset(sigset_t *set) 函數:将set集合按位填充為1
sigaddset(sigset_t *set,signum) 函數:将signum信号添加到set集合
sigdelset(sigset_t *set,signum) 函數:将signum信号從set集合删除
sigismember(sigset_t,signum) 函數:判斷signum信号是否在set集合裡
注意:sigaddset()、sigdelset()、sigismember()等函數調用之前必須先調用sigemptyset()或者sigfillset()函數初始化信号集。
sigprocmask(int how,sigset_t *set,sigset_t *oldset) 函數:用來屏蔽、解除屏蔽某個信号,本質是讀取并修改PCB(在程序核心裡)裡的信号屏蔽字mask。
how:為SIG_BLOCK時,set表示需要屏蔽的信号,相當于mask=mask|set,"或"操作
為SIG_UNBLOCK時,set表示需要解除的信号,相當于mask=mask&~set,"取反"後再"與"操作
為SIG_SETMASK時,set表示用于替換之前的信号屏蔽字,相當于mask=set,set成為新的信号屏蔽字。
set:傳入參數,需要操作的信号集
oldset:傳出參數,傳回之前的信号集額,一般用于恢複時使用。
sigpending(sigset_t *set): 函數:讀取目前程序的未決信号集,set為傳出參數。
pause() 函數:主動挂起,處于阻塞狀态,等等任一信号送達喚醒,該信号不能是被屏蔽的,不然沒法送達呀。
sigsuspend 函數:挂起等待信号。類似于pause函數,但pause有時序問題,可以使用sigsuspend函數解決時序問題。
sigqueue 函數:對應kill函數,信号傳參,攜帶union參數。傳遞指針的話,本程序内才有意義。因為每個程序都有自己獨立的空間,程序間傳遞指針是沒有意義的。
6.信号捕捉函數
signal(signum,handler)函數:
捕捉指定的signum信号,觸發回調handler函數。handler是一個函數指針。由于曆史原因,相容性較差,很少使用。
sigaction(signum,struct sigaction *act,struct sigaction *oldact)函數
捕捉指定的signum信号,回調函數再act結構體裡。act為傳入參數,新的處理方式。oldact為傳出參數,傳回舊的處理方式,一般用于之前恢複處理方式時使用。
struct sigaction{
void (*sa_handler)(int);//信号捕捉後的處理函數,也可以指定為SIG_IGN表示忽悠,SIG_DEL表示預設處理方式
void (*sa_sigaction)(int,siginfo_t*,void*);//sa_flags指定為SA_SIGINFO時信号捕捉後改為調用該函數,不調用sa_handler函數
sigset_t sa_mask;//處理函數執行期間(可能執行很長時間呀)的信号屏蔽字,表示處理函數執行期間屏蔽哪些信号
int sa_flags;//特定辨別位,通常為0表示預設屬性
void (*sa_restorer)(void);//已過時,已棄用
}
處理函數執行期間,屏蔽字由sa_mask指定,預設情況下處理函數執行期間,被捕捉信号自動屏蔽,正常信号不支援排隊,多次産生同一信号可能隻産生一次觸發
7.SIGCHLD信号
子程序終止時,或者子程序收到SIGSTOP信号暫停時,或者子程序收到SIGCONT信号後繼續運作時,都會發送該信号。