sigaction函數的功能是檢查或修改與指定信號相關聯的處理動作(可同時兩種操作)。
他是POSIX的信號接口,而signal()是標准C的信號接口(如果程序必須在非POSIX系統上運行,那么就應該使用這個接口)
給信號signum設置新的信號處理函數act, 同時保留該信號原有的信號處理函數oldact
int sigaction(int signo,const struct sigaction *restrict act, struct sigaction *restrict oact); |
第二、第三個參數為,sigaction結構類型定義如下:
struct sigaction{ |
sa_handler:字段包含一個信號捕捉函數的地址
sa_mask:字段說明了一個信號集,在調用該信號捕捉函數之前,這一信號集要加進進程的信號屏蔽字中。
即執行信號處理函數期間,阻塞信號屏蔽字中的信號,執行結束后再處理這期間發生的信號(sa_mask集中的信號)。注:阻塞的意思是延遲相應信號
sa_flag :是一個選項,注意:這個選項只與sigaction函數注冊的信號有關聯,與sa_mask中的信號無任何關系。
SA_INTERRUPT 由此信號中斷的系統調用不會自動重啟 SA_SIGINFO 提供附加信息,一個指向siginfo結構的指針以及一個指向進程上下文標識符的指針 SA_NODEFER 一般情況下,當信號處理函數運行時,內核將阻塞(sigaction函數注冊時的信號)。但是如果設置了SA_NODEFER標記, 那么在該信號處理函 數運行時,內核將不會阻塞該信號。 SA_RESETHAND 當調用信號處理函數時或信號處理函數結束后,將信號的處理設置為系統默認值。 |
最后一個參數是一個替代的信號處理程序,當設置SA_SIGINFO時才會用他。
例子:
#include <stdio.h> #include <signal.h> #include <unistd.h> void show_handler(int sig) { printf("I got signal %d\n", sig); int i; for(i = 0; i < 5; i++) { printf("i = %d\n", i); sleep(1); } } int main(void) { int i = 0; struct sigaction act, oldact; act.sa_handler = show_handler; sigaddset(&act.sa_mask, SIGQUIT); //見注(1) act.sa_flags = SA_RESETHAND | SA_NODEFER; //見注(2) //act.sa_flags = 0; //見注(3) sigaction(SIGINT, &act, &oldact); while(1) { sleep(1); printf("sleeping %d\n", i); i++; } }
注:
(1) 如果在信號SIGINT(Ctrl + c)的信號處理函數show_handler執行過程中,本進程收到信號SIGQUIT(Crt+\),將阻塞該信號,直到show_handler執行結束才會處理信號SIGQUIT。
(2) SA_NODEFER 一般情況下, 當信號處理函數運行時,內核將阻塞<該給定信號 -- SIGINT>。但是如果設置了SA_NODEFER標記, 那么在該信號處理函數運行時,內核將不會阻塞該信號。 SA_NODEFER是這個標記的正式的POSIX名字(還有一個名字SA_NOMASK,為了軟件的可移植性,一般不用這個名字)
SA_RESETHAND 當調用信號處理函數時,將信號的處理函數重置為缺省值。 SA_RESETHAND是這個標記的正式的POSIX名字(還有一個名字SA_ONESHOT,為了軟件的可移植性,一般不用這個名字)
(3) 如果不需要重置該給定信號的處理函數為缺省值;並且不需要阻塞該給定信號(無須設置sa_flags標志),那么必須將sa_flags清零,否則運行將會產生段錯誤。但是sa_flags清零后可能會造成信號丟失!
http://webcache.googleusercontent.com/search?q=cache:B2HsD1Zf2f8J:hi.baidu.com/operationsystem/blog/item/bb215411f4dc61f4c2ce79e6.html/cmtid/c150423c8b8feae13d6d97b0+sigaction&cd=1&hl=zh-CN&ct=clnk