1. 程式人生 > >Windows下的訊號(Signal)

Windows下的訊號(Signal)

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 handlerstatic 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