sigaction()之sa_mask


man文檔描述:

sa_mask gives a mask of signals which should be blocked during execution of the signal handler. In addition, the signal which triggered the
handler will be blocked, unless the SA_NODEFER flag is used.

sigset_t sa_mask 是一個信號集,在調用該信號捕捉函數之前,將需要block的信號加入這個sa_mask,僅當信號捕捉函數正在執行時,才阻塞sa_mask中的信號,當從信號捕捉函數返回時進程的信號屏蔽字復位為原先值。
Q1:這個復位動作是sigaction函數內部處理,還是由調用者自己處理呢?

  由sigaction函數自動復位,不用我自己再去處理。

Q2:設置sa_mask的目的?

  在調用信號處理程序時就能阻塞某些信號。注意僅僅是在信號處理程序正在執行時才能阻塞某些信號,如果信號處理程序執行完了,那么依然能接收到這些信號。
在信號處理程序被調用時,操作系統建立的新信號屏蔽字包括正被遞送的信號,也就是說自己也被阻塞,除非設置了SA_NODEFER。
因此保證了在處理一個給定的信號時,如果這種信號再次發生,通常並不將它們排隊,所以如果在某種信號被阻塞時它發生了5次,那么對這種信號解除阻塞后,其信號處理函數通常只會被調用一次。

Q3:對於不同信號,當信號A被捕捉到並信號A的handler正被調用時,信號B產生了,
  3.1如果信號B沒有被設置阻塞,那么正常接收信號B並調用自己的信號處理程序。另外,如果信號A的信號處理程序中有sleep函數,那么當進程接收到信號B並處理完后,sleep函數立即返回(如果睡眠時間足夠長的話)
  3.2如果信號B有被設置成阻塞,那么信號B被阻塞,直到信號A的信號處理程序結束,信號B才被接收並執行信號B的信號處理程序。

    如果在信號A的信號處理程序正在執行時,信號B連續發生了多次,那么當信號B的阻塞解除后,信號B的信號處理程序只執行一次。
    如果信號A的信號處理程序沒有執行或已經執行完,信號B不會被阻塞,正常接收並執行信號B的信號處理程序。
Q4:對於相同信號,當一個信號A被捕捉到並信號A的handler正被調用時
  4.1 又產生了一個信號A,第二次產生的信號被阻塞,直到第一次產生的信號A處理完后才被遞送;
  4.2 如果連續產生了多次信號,當信號解除阻塞后,信號處理函數只執行一次。

 

沒有設置SIGUSR2 阻塞的情況:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <string.h>
 5 #include <signal.h>
 6 #include <errno.h>
 7 
 8 #define BUFSIZE (1024)
 9 
10 void sig_usr(int signo)
11 {
12     int nRemainSecond = 0;
13 
14     if (signo == SIGUSR1)
15     {
16         printf("received SIGUSR1=%d\n", SIGUSR1);
17         nRemainSecond = sleep(50);
18         printf("over...nRemainSecond=%d\n", nRemainSecond);
19     }
20     else if (signo == SIGUSR2)
21     {
22         printf("received SIGUSR2=%d\n", SIGUSR2);
23     }
24     
25 }
26 
27 int main(int argc, char** argv)
28 {
29     int nSize = 0;
30     char acBuf[BUFSIZE] = {0};
31     struct sigaction act, oact;
32     sigset_t oldmask;
33 
34     act.sa_handler = sig_usr;
35 
36     sigemptyset(&act.sa_mask);
37     //sigaddset(&act.sa_mask, SIGUSR2);
38     sigaddset(&act.sa_mask, SIGQUIT); 39 
40     act.sa_flags = 0|SA_INTERRUPT;
41     sigaction(SIGUSR1, &act, &oact);
42  signal(SIGUSR2, sig_usr); 43 
44     while(1)
45     {
46         memset(acBuf, '\0', BUFSIZE);
47         nSize = read(STDIN_FILENO, acBuf, BUFSIZE); 
48         if (errno == EINTR)
49             printf("interrupt, size=%d\n", nSize);
50 
51         if (1 == nSize && acBuf[0] == 10)
52             ;
53         else if (nSize != -1)
54         {
55             printf("nSize=%d, acBuf=%s", nSize, acBuf);
56         }
57     }
58 
59     return 0;
60 }

result1:

首先,發送SIGUSR1給a.out,執行sig_usr(),在該函數執行期間,連續發送3次SIGUSR1信號,當第一次的SIGUSR1的sig_usr()執行完后,sig_usr()再執行一次;當第二次sig_usr()執行完后,read()中斷返回,再次發送SIGQUIT信號時,依然能接收並正常退出。--->解釋了Q4

 

result2:

首先,發送SIGUSR1給a.out,執行sig_usr(),在該函數執行期間,發送SIGUSR2(沒有被設置成阻塞)並正常接收處理后,由於捕捉到SIGUSR2信號,SIGUSR1中的sleep()立即返回了,此時SIGUSR1的信號處理函數結束了。再發送一個SIGUSR1,在執行sig_usr()期間,發送一個SIGQUIT(被設置阻塞)信號,顯然該信號被阻塞了,直到sig_usr執行完后,才遞送SIGQUIT。--->解釋了Q3。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM