1. 程式人生 > >Linux 訊號 向訊號處理函式傳遞資料

Linux 訊號 向訊號處理函式傳遞資料

1.Linux 訊號是一種非同步機制,程序可以接收一個訊號,並有相應的處理操作,如果我們需要改變當該訊號發生時的預設行為,我們就需要捕捉該訊號,並且自己書寫訊號處理函式。

2.這種訊號處理函式就跟中斷差不多,當一個程序接收到一個訊號時,程序會暫停當前的執行流,轉而呼叫訊號處理函式,訊號處理函式結束之後,會繼續剛才的執行流繼續執行。

3.如果程序已經阻塞在一些系統呼叫的時候,訊號發生之後,是不會重新呼叫這些系統呼叫的,但是也可以設定成繼續進行這些系統呼叫。

 

我們可以使用sigaction函式來對一個訊號進行捕捉,並且指定這個訊號的處理函式。這個是POSIX.1標準,如果在不支援POSIX.1的系統上面,那麼還是需要呼叫signal這個標準C函式。

對於訊號處理函式是否可以接收引數來說,我們可以把訊號處理函式分成兩種:一種可以接收使用者傳送過來的資料,另外一種不能得到使用者傳送過來的資料。

① 不能接收使用者傳送過來的資料:

int firstFunc(int signo) {
    printf("In the handler");
}

struct sigaction newAction, oldAction;
memset(&newAction, 0, sizeof(newAction))
newAction.sa_flag = 0;
newAction.sa_handler = firstFunc;
sigemptyset(&sa_mask)
sigaction(SIGINT, &newAction, &oldAction)

這樣,當此程序收到SIGINT訊號的時候,就會呼叫firstFunc函式,呼叫完畢之後會繼續主函式的執行流。

② 可以接收使用者傳送過來的資料:

        有時候我們想在這個訊號發生的時候,傳遞一些我們需要的資訊到訊號處理函式裡面,這個時候我們就需要用另外一種方式:

int secondFunc(int signo, siginfo* info, void* context) {  // (1)
    Data* data = (Data*)info->si_value.sival_ptr;
    /*Deal with data......*/
}

struct sigaction newAction, oldAction;
memset(&newAction, 0, sizeof(newAction))
newAction.sa_flag = SA_SIGINFO;  // (2)
sigemptyset(&newAction.sa_mask);
newAction.sa_sigaction = secondFunc;  // (3)
Data* data;
/*Construct your data struct.*/
union sigval curVal;   
curVal.sival_ptr = (void*)data;
sigqueue(getpid(), SIGINT, curVal);   // (4)

上面需要注意的就是4點:

(1)這個是訊號處理函式的原型,多出來了兩個引數。只能這樣寫。

(2)需要在sigaction裡面的sa_flag 新增SA_SIGINFO,表示我們會傳遞一些資訊到錯誤處理函式裡面。

(3)使用SA_SIGINFO之後,我們需要使用sa_sigaction這個成員變數,而不是sa_handler。

(4)我們需要使用sigqueue函式來對特定的程序傳送特定的訊號,並且curVal這個聯合體裡面攜帶了我們需要傳遞的資料的指標。

兩種方式需要按照特定的需求來選用。