函式名: signal
表頭檔案#include<signal.h>
功 能:設定某一信號的對應動作
函式原型:void (*signal(int signum,void(* handler)(int)))(int);
或者:typedef void (*sig_t)( int );
sig_t signal(int signum,sig_t handler);
參數說明:
第一個參數signum指明了所要處理的信號類型,它可以取除了SIGKILL和SIGSTOP外的任何一種信號。
第二個參數handler描述了與信號關聯的動作,它可以取以下三種值:
(1)一個無返回值的函式地址
此函式必須在signal()被調用前申明,handler中為這個函式的名字。當接收到一個類型為signum的信號時,就執行handler 所指定的函式。這個函式應有如下形式的定義:
void func(int sig);
(2)SIG_IGN
這個符號表示忽略該信號,執行了相應的signal()調用後,進程會忽略類型為sig的信號。
(3)SIG_DFL
這個符號表示恢復系統對信號的默認處理。
函式說明:
signal()會依參數signum 指定的信號編號來設定該信號的處理函式。當指定的信號到達時就會跳轉到參數handler指定的函式執行。當一個信號的信號處理函式執行時,如果進程又接收到了該信號,該信號會自動被儲存而不會中斷信號處理函式的執行,直到信號處理函式執行完畢再重新調用相應的處理函式。但是如果在信號處理函式執行時進程收到了其它類型的信號,該函式的執行就會被中斷。
返回值:返回先前的信號處理函式指針,如果有錯誤則返回SIG_ERR(-1)。
下面的情況可以產生Signal:
按下CTRL+C產生SIGINT
硬體中斷,如除0,非法記憶體訪問(SIGSEV)等等
Kill函式可以對進程傳送Signal
Kill命令。實際上是對Kill函式的一個包裝
軟體中斷。如當Alarm Clock逾時(SIGURG),當Reader中止之後又向管道寫數據(SIGPIPE),等等
1.按下CTRL+C產生SIGINT
2.硬體中斷,如除0,非法記憶體訪問(SIGSEV)等等
3.Kill函式可以對進程傳送Signal
4.Kill命令。實際上是對Kill函式的一個包裝
5.軟體中斷。如當Alarm Clock逾時(SIGURG),當Reader中止之後又向管道寫數據(SIGPIPE),等等
程式例:
/* This example installs a signal handler routine for SIGFPE,
catches an integer overflow condition, makes an adjustment
to AX register, and returns. This example program MAY cause
your computer to crash, and will produce runtime errors
depending on which memory model is used.
*/
#pragma inline
#include <stdio.h>
#include <signal.h>
void Catcher(int sig, int type, int *reglist)
{
printf("Caught it!\n");
*(reglist + 8) = 3; /* make return AX = 3 */
}
int main(void)
{
signal(SIGFPE, Catcher);
asm mov ax,07FFFH /* AX = 32767 */
asm inc ax /* cause overflow */
asm into /* activate handler */
/* The handler set AX to 3 on return. If that hadn't happened,
there would have been another exception when the next 'into'
was executed after the 'dec' instruction. */
asm dec ax /* no overflow now */
asm into /* doesn't activate */
return 0;
}
2 Signals:
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專用,進程超過資源限制的時候傳送 |
注意點
1、不要使用低級的或者STDIO.H的IO函式
2、不要使用對操作
3、不要進行系統調用
4、不是浮點信號的時候不要用 longjmp
5、signal函式是由ISO C定義的。因為ISO C不涉及多進程,進程組以及終端I/O等,所以他對信號的定義非常含糊,以至於對UNIX系統而言幾乎毫無用處。
備註:因為signal的語義與現實有關,所以最好使用sigaction函式替代本函式。