1. 程式人生 > >signal ()函式詳細介紹

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專用,程序超過資源限制的時候發