1. 功能
設置某一信號的對應動作
2. 聲明
- #include <signal.h>
- typedef void (*sighandler_t)(int);
- sighandler_t signal(int signum, sighandler_t handler);
3. 參數說明
第一個參數signum:指明瞭所要處理的信號類型,它可以取除了SIGKILL和SIGSTOP外的任何一種信號。
第二個參數handler:描述了與信號關聯的動作,它可以取以下三種值:
(1)SIG_IGN
這個符號表示忽略該信號。
例如:
- #include <stdio.h>
- #include <signal.h>
- int main(int argc, char *argv[]) {
- signal(SIGINT, SIG_IGN);
- while(1);
- return 0;
- }
SIGINT信號代表由InterruptKey產生,通常是CTRL +C 或者是DELETE 。執行上述代碼時,按下CTRL + C程序沒有反應。這就對了,如果我們想結束該程序可以按下CTRL +\來結束,當我們按下CTRL +\組合鍵時,產生了SIGQUIT信號,此信號並沒有被忽略。
(2)SIG_DFL
這個符號表示恢復對信號的系統默認處理。不寫此處理函數默認也是執行系統默認操作。
例如
- #include <stdio.h>
- #include <signal.h>
- int main(int argc, char *argv[]) {
- signal(SIGINT, SIG_DFL);
- while(1);
- return 0;
- }
這時就可以按下CTRL +C 來終止該進程了。把signal(SIGINT, SIG_DFL);這句去掉,效果是一樣的
(3)sighandler_t類型的函數指針
上面提到了sighandler_t類型聲明:
- typedef void (*sighandler_t)(int);
- sighandler_t signal(int signum, sighandler_t handler);
此函數必須在signal()被調用前申明,handler中爲這個函數的名字。當接收到一個類型爲sig的信號時,就執行handler 所指定的函數。(int)signum是傳遞給它的唯一參數。執行了signal()調用後,進程只要接收到類型爲sig的信號,不管其正在執行程序的哪一部分,就立即執行func()函數。當func()函數執行結束後,控制權返回進程被中斷的那一點繼續執行。
例如
- #include <stdio.h>
- #include <signal.h>
- typedef void (*signal_handler)(int);
-
- void signal_handler_fun(int signum) {
- printf("catch signal %d\n", signum);
- }
-
- int main(int argc, char *argv[]) {
- signal(SIGINT, signal_hander_fun);
- while(1);
- return 0;
- }
執行時,當我們按下CTRL +C鍵時,會執行我們定義的信號處理函數。
- catch signal 2
- catch signal 2
- catch signal 2
- catch signal 2
每當我們按下CTRL +C鍵時會打印該信號的number.可以看出該信號的num爲2。要想退出可以按下CTRL +\ 打印結果爲最後一行。
4. 函數說明
signal()會依參數signum 指定的信號編號來設置該信號的處理函數。當指定的信號到達時就會跳轉到參數handler指定的函數執行。
當一個信號的信號處理函數執行時,如果進程又接收到了該信號,該信號會自動被儲存而不會中斷信號處理函數的執行,直到信號處理函數執行完畢再重新調用相應的處理函數。但是如果在信號處理函數執行時進程收到了其它類型的信號,該函數的執行就會被中斷。
5. 返回值
返回先前的信號處理函數指針,如果有錯誤則返回SIG_ERR(-1)。
6. 一些常用的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專用,進程超過資源限制的時候發 |