Windows下的signal,Piaoger一直沒有機會用到,今天既然在一個Console程式中碰到了,就很有必要把玩把玩,廣搜天下,並做些筆記:
>> Windows下的訊號(Signal)
訊號是進程在運行過程中,由自身產生或由進程外部發過來的訊息。
訊號是硬體中斷的軟體類比(非強制中斷)。每個訊號用一個整型常量宏表示,以SIG開頭,比如SIGCHLD、SIGINT等,它們在系統標頭檔中<signal.h>定義。
這玩意兒據說Linux也有,但相當不一樣,有時間可以zhuangB看看。
>> 訊號的來源
訊號的產生來自核心,讓核心產生訊號的請求來自3個地方:使用者、核心護著進程。
++ 使用者:使用者能夠通過輸入CTRL+c、Ctrl+,或者是終端驅動程式分配給訊號控制字元的其他任何鍵來請求核心產生訊號;
++ 核心:當進程執行出錯時,核心會給進程發送一個訊號,例如非法段存取(記憶體訪問違規)、浮點數溢出等
++ 進程:一個進程可以通過系統調用kill給另一個進程發送訊號,一個進程可以通過訊號和另外一個進程進行通訊。
由進程的某個操作產生的訊號稱為同步訊號(synchronous signals),例如除0;由使用者擊鍵之類的進程外來事件產生的訊號叫做非同步訊號。(asynchronous signals)。
>> 訊號的處理
進程接收到訊號以後,可以有如下3種選擇進行處理:
++ 接收預設處理:接收預設處理的進程通常會導致進程本身消亡。例如串連到終端的進程,使用者按下CTRL+c,將導致核心向進程發送一個SIGINT的訊號,進程如果不對該訊號做特殊的處理,系統將採用預設的方式處理該訊號,即終止進程的執行;
++ 忽略訊號:進程可以通過代碼,顯示地忽略某個訊號的處理,例如:signal(SIGINT,SIGDEF);但是某些訊號是不能被忽略的,
++ 捕捉訊號並處理:進程可以事先註冊訊號處理函數,當接收到訊號時,由訊號處理函數自動貼齊並且處理訊號。
有兩個訊號既不能被忽略也不能被捕捉,它們是SIGKILL和SIGSTOP。即進程接收到這兩個訊號後,只能接受系統的預設處理,即終止線程。
>> Windows Signal Types
#include <signal.h>
// Ctrl-C handler
static int b_ctrl_c = 0;
static int b_exit_on_ctrl_c = 0;
// Signal types
#define SIGINT 2 // interrupt(Ctrl+C中斷)
#define SIGILL 4 // illegal instruction - invalid function image(非法指令)
#define SIGFPE 8 // floating point exception(浮點異常)
#define SIGSEGV 11 // segment violation(段錯誤)
#define SIGTERM 5 // Software termination signal from kill(Kill發出的軟體終止)
#define SIGBREAK 21 //Ctrl-Break sequence(Ctrl+Break中斷)
#define SIGABRT 22 // abnormal termination triggered by abort call(Abort)
>> Windows Signal Handling
訊號處理函數用於設定訊號處理的Handler。
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
signal用於設定訊號的捕捉函數。signal如果調用成功,返回以前該訊號的處理函數的地址,否則返回 SIG_ERR。
++ signum:要捕捉的訊號,
++ handler: 函數指標,表示要對該訊號進行捕捉的函數,該參數也可以是SIG_DEF(表示交由系統預設處理,無需理會)或SIG_IGN(表示忽略掉該訊號而不做任何處理)。
sighandler_t是訊號捕捉函數,由signal函數註冊,註冊以後,在整個進程運行過程中均有效,並且對不同的訊號可以註冊同一個訊號捕捉函數。唯一的傳入參數表示訊號值。
>> MSDN上的小例子
這個小例子示範了如何處理Abort訊號。
// Use signal to attach a signal handler to the abort routine
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <tchar.h>
void SignalHandler(int signal)
{
printf("Application aborting...\n");
}
int main()
{
typedef void (*SignalHandlerPointer)(int);
SignalHandlerPointer previousHandler;
previousHandler = signal(SIGABRT, SignalHandler);
abort();
}
>> More
據說還有更NB與可靠的sigaction訊號處理機制,既然是初來乍到,就留到以後來瞭解吧。
- Piaoger