signal()函數理解
在<signal.h> 這個頭文件中。
signal(參數1,參數2);
參數1:我們要進行處理的信號。系統的信號我們可以再終端鍵入 kill -l查看(共64個)。其實這些信號時系統定義的宏。
參數2:我們處理的方式(是系統默認還是忽略還是捕獲)。
一般有3中方式進行操作。
(1)eg: signal(SIGINT ,SIG_ING );
//SIG_ING 代表忽略SIGINT信號,SIGINT信號代表由InterruptKey產生,通常是CTRL +C 或者是DELETE 。發送給所有ForeGround Group的進程。
下面我們寫個死循環:
這時我們保存執行。
按下CTRL _C程序沒有反應。這就對了
如果我們想結束該程序可以按下CTRL +\來結束
其實當我們按下CTRL +\組合鍵時,是產生了SIGQUIT信號
(2)eg: signal(SIGINT ,SIG_DFL );
//SIGINT信號代表由InterruptKey產生,通常是CTRL +C或者是DELETE。發送給所有ForeGroundGroup的進程。 SIG_DFL代表執行系統默認操作,其實對於大多數信號的系統默認動作時終止該進程。這與不寫此處理函數是一樣的。
我們將上面的程序改成
這時就可以按下CTRL +C 來終止該進程了。把signal(SIGINT,SIG_DFL);這句去掉,效果是一樣的。
(3) void ( *signal( int sig, void (* handler)( int )))( int );
int (*p)();
這是一個函數指針, p所指向的函數是一個不帶任何參數, 並且返回值爲int的一個函數.
int (*fun())();
這個式子與上面式子的區別在於用fun()代替了p,而fun()是一個函數,所以說就可以看成是fun()這個函數執行之後,它的返回值是一個函數指針,這個函數指針(其實就是上面的p)所指向的函數是一個不帶任何參數,並且返回值爲int的一個函數.
void (*signal(int signo, void (*handler)(int)))(int);就可以看成是signal()函數(它自己是帶兩個參數,一個爲整型,一個爲函數指針的函數),而這個signal()函數的返回值也爲一個函數指針,這個函數指針指向一個帶一個整型參數,並且返回值爲void的一個函數.
在寫信號處理函數時對於信號處理的函數也是void sig_fun(int signo);這種類型,恰好與上面signal()函數所返回的函數指針所指向的函數是一樣的.void ( *signal() )( int );
signal是一個函數, 它返回一個函數指針, 後者所指向的函數接受一個整型參數 且沒有返回值, 仔細看, 是不是siganal( int signo, void (*handler)(int) )的第2個參數了,對了,其實他所返回的就是 signal的第2個信號處理函數,指向信號處理函數,就可以執行函數了( signal內部時, signal把信號做爲參數傳遞給handler信號處理函數,接着 signal函數返回指針,並且又指向信號處理函數, 就開始執行它)
那麼,signal函數的參數又是如何呢?signal函數接受兩個參數:一個整型的信號編號,以及一個指向用戶定義的信號處理函數的指針。我們此前已經定義了指向用戶定義的信號處理函數的指針sfp:
void (*sfp)(int); |
sfp 的類型可以通過將上面的聲明中的sfp去掉而得到,即void (*)(int)。此外,signal函數的返回值是一個指向調用前的用戶定義信號處理函數的指針,這個指針的類型與sfp指針類型一致。因此,我們可以如下聲明signal函數:
void (*signal(int, void(*)(int)))(int); |
同樣地,使用typedef可以簡化上面的函數聲明:
typedef void (*HANDLER)(int); |
Ok;看個例子:
此程序是對當我們按下CTRL +C鍵時,會執行我們定義的信號處理函數。
每當我們按下CTRL +C鍵時會打印該信號的number.可以看出該信號的num爲2
要想退出可以按下CTRL +\ 打印結果爲最後一行。
一些常用的Signal 如下:
注:下面是從百度文庫中找的(*^__^*) 嘻嘻……
Signal | Description |
SIGABRT | 由調用abort函數產生,進程非正常退出 |
SIGALRM | 用alarm函數設置的timer超時或setitimer函數設置的interval timer超時 |
SIGBUS | 某種特定的硬件異常,通常由內存訪問引起 |
SIGCANCEL | 由Solaris Thread Library內部使用,通常不會使用 |
SIGCHLD | 進程Terminate或Stop的時候,SIGCHLD會發送給它的父進程。缺省情況下該Signal會被忽略 |
SIGCONT | 當被stop的進程恢復運行的時候,自動發送 |
SIGEMT | 和實現相關的硬件異常 |
SIGFPE | 數學相關的異常,如被0除,浮點溢出,等等 |
SIGFREEZE | Solaris專用,Hiberate或者Suspended時候發送 |
SIGHUP | 發送給具有Terminal的Controlling Process,當terminal被disconnect時候發送 |
SIGILL | 非法指令異常 |
SIGINFO | BSD signal。由Status Key產生,通常是CTRL+T。發送給所有Foreground Group的進程 |
SIGINT | 由Interrupt Key產生,通常是CTRL+C或者DELETE。發送給所有ForeGround Group的進程 |
SIGIO | 異步IO事件 |
SIGIOT | 實現相關的硬件異常,一般對應SIGABRT |
SIGKILL | 無法處理和忽略。中止某個進程 |
SIGLWP | 由Solaris Thread Libray內部使用 |
SIGPIPE | 在reader中止之後寫Pipe的時候發送 |
SIGPOLL | 當某個事件發送給Pollable Device的時候發送 |
SIGPROF | Setitimer指定的Profiling Interval Timer所產生 |
SIGPWR | 和系統相關。和UPS相關。 |
SIGQUIT | 輸入Quit Key的時候(CTRL+\)發送給所有Foreground Group的進程 |
SIGSEGV | 非法內存訪問 |
SIGSTKFLT | Linux專用,數學協處理器的棧異常 |
SIGSTOP | 中止進程。無法處理和忽略。 |
SIGSYS | 非法系統調用 |
SIGTERM | 請求中止進程,kill命令缺省發送 |
SIGTHAW | Solaris專用,從Suspend恢復時候發送 |
SIGTRAP | 實現相關的硬件異常。一般是調試異常 |
SIGTSTP | Suspend Key,一般是Ctrl+Z。發送給所有Foreground Group的進程 |
SIGTTIN | 當Background Group的進程嘗試讀取Terminal的時候發送 |
SIGTTOU | 當Background Group的進程嘗試寫Terminal的時候發送 |
SIGURG | 當out-of-band data接收的時候可能發送 |
SIGUSR1 | 用戶自定義signal 1 |
SIGUSR2 | 用戶自定義signal 2 |
SIGVTALRM | setitimer函數設置的Virtual Interval Timer超時的時候 |
SIGWAITING | Solaris Thread Library內部實現專用 |
SIGWINCH | 當Terminal的窗口大小改變的時候,發送給Foreground Group的所有進程 |
SIGXCPU | 當CPU時間限制超時的時候 |
SIGXFSZ | 進程超過文件大小限制 |
SIGXRES | Solaris專用,進程超過資源限制的時候發送 |