signal ()函式詳細介紹
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專用,程序超過資源限制的時候發 |