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這個聯合體裡面攜帶了我們需要傳遞的資料的指標。
兩種方式需要按照特定的需求來選用。