【C】——sigprocmask 阻塞进程信号

1、有时候不希望在接到信号时就立即停止当前执行,去处理信号,同时也不希望忽略该信号,而是延时一段时间去调用信号处理函数。这种情况是通过阻塞信号实现的。

 

2、信号阻塞和忽略信号的区别。

阻塞的概念和忽略信号是不同的。操作系统在信号被进程解除阻塞之前不会讲信号传递出去,被阻塞的信号也不会影响进程的行为,信号只是暂时被阻止传递。当进程忽略一个信号时,信号会被传递出去但进程会将信号丢弃。

 

3、信号阻塞系统调用,它们的都起到阻塞的作用,它们不是协作使用的。

 

[cpp]  view plain copy print ?
 
  1. #include <signal.h>  
  2.   
  3. int sigprocmask(ubt how,const sigset_t*set,sigset_t *oldset);  
  4.   
  5. int sigsuspend(const sigset_t*sigmask);  

 

 

 

sigprocmask设定对信号屏蔽集内的信号的处理方式(阻塞或不阻塞)。


参数:

how:用于指定信号修改的方式,可能选择有三种

SIG_BLOCK//将set所指向的信号集中包含的信号加到当前的信号掩码中。即信号掩码和set信号集进行或操作。

SIG_UNBLOCK//将set所指向的信号集中包含的信号从当前的信号掩码中删除。即信号掩码和set进行与操作。

SIG_SETMASK //将set的值设定为新的进程信号掩码。即set对信号掩码进行了赋值操作。

 

set:为指向信号集的指针,在此专指新设的信号集,如果仅想读取现在的屏蔽值,可将其置为NULL。

oldset:也是指向信号集的指针,在此存放原来的信号集。可用来检测信号掩码中存在什么信号。

返回说明:

成功执行时,返回0。失败返回-1,errno被设为EINVAL。

 

sigprocmask示例(演示添加信号掩码):

 

 

 1 #include <stdio.h>

 2 #include <signal.h>

 3 void checkset();

 4 

 5 void main()

 6 {

 7      sigset_tblockset;

 8      sigemptyset(&blockset);

 9      sigaddset(&blockset,SIGINT);

10      sigaddset(&blockset,SIGTSTP);

11 

12     &nbsp;checkset();

13 

14      sigprocmask(SIG_SETMASK,&blockset,NULL);

15      checkset();

16 

17    &nbsp; sigaddset(&blockset,SIGTERM);

18      sigprocmask(SIG_BLOCK,&blockset,NULL);

19      checkset();

20 

21      sigdelset(&blockset,SIGTERM);

22      sigprocmask(SIG_UNBLOCK,&blockset,NULL);

23      checkset();

24 }

25 

26 void checkset()

27 {

28 

29      sigset_tset set;

30      printf("checksetstart:\n");

31 

32      if(sigprocmask(0,NULL,&set)<0)

33      {

34      printf("checksetsigprocmask error!!\n");

35      exit(0);

36      }

37 

38      if(sigismember(&set,SIGINT))

39      printf("sigint\n");

40      if(sigismember(&set,SIGTSTP))

41      printf("sigtstp\n");

42 

43      if(sigismember(&set,SIGTERM))

44      printf("sigterm\n");

45       printf("checksetend\n");

46 }

 

【C】——sigprocmask 阻塞进程信号

 

 

 

sigprocmask示例(演示添某部分代码不被信号打搅):

 

 1 #include <stdio.h>

 2 #include <signal.h>

 3 void checkset();

 4 

 5 void func();

 6 void main()

 7 {

 8      sigset_tblockset,oldblockset,pendmask;

 9      printf("pid:%ld\n",(long)getpid());

10 

11      signal(SIGINT,func); //信号量捕捉函数,捕捉到SIGINT,跳转到函数指针func处执行

12 

13     sigemptyset(&blockset); //初始化信号量集

14     sigaddset(&blockset,SIGTSTP); //将SIGTSTP添加到信号量集中

15    &nbsp;sigaddset(&blockset,SIGINT);//将SIGINT添加到信号量集中

16 

17    sigprocmask(SIG_SETMASK,&blockset,&oldblockset); //将blockset中的SIGINT,SIGTSTP阻塞掉,并保存当前信号屏蔽字

18 

19      /*执行以下程序时,不会被信号打搅*/

20     checkset();

21    &nbsp;sleep(5);

22      sigpending(&pendmask); //检查信号是悬而未决的

23      if(sigismember(&pendmask,SIGINT)) //SIGINT是悬而未决的。所谓悬而未决,是指SIGQUIT被阻塞还没有被处理

24          printf("SIGINTpending\n");

25 

26      /*免打搅结束*/

27 

28      sigprocmask(SIG_SETMASK,&oldblockset,NULL); //恢复被屏蔽的信号SIGINT SIGTSTP

29      printf("SIGINTunblocked\n");

30      sleep(6);

31 }

32 

33 void checkset()

34 {

35      sigset_tset;

36      printf("checksetstart:\n");

37      if(sigprocmask(0,NULL,&set)<0)

38      {

39      printf("checksetsigprocmask error!!\n");

40      exit(0);

41      }

42      if(sigismember(&set,SIGINT))

43      printf("sigint\n");

44 

45      if(sigismember(&set,SIGTSTP))

46      printf("sigtstp\n");

47 

48      if(sigismember(&set,SIGTERM))

49      printf("sigterm\n");

50 

51 &nbsp;    printf("checksetend\n");

52 

53 }

54 void func()

55 {

56      printf("hellofunc\n");

57 }

 sigeprocmask函数通常和sigemptyset、sigfillset、sigaddset、sigdelset、 sigismember函数配合使用,主要有两种用途:

1.我们不希望某些不太重要的信号来影响我们的进程,我们就可以把这些信号添加到信号屏蔽集中。使它们不打扰进程的执行。

2.如果系统现在很忙,没有时间及时相应信号,进程可以先把信号阻塞掉,等系统有空闲时间在去相应,这也保证了信号的可靠性。

 

例二:

 1 #include<stdio.h>

 2 #include<stdlib.h>

 3 #include<signal.h>

 4 

 5 sigset_t newmask,oldmask,pendmask;

 6 

 7 void sig_usr(int signo)

 8 {

 9     printf("this is sig_usr!\n");

10 

11 }

12 

13 int main(int argc, char *argv[])

14 {

15 

16     if(signal(SIGUSR1,sig_usr) == SIG_ERR){

17         printf("signal error!\n");

18         exit(1);

19     }

20 

21     sigemptyset(&newmask);

22     sigaddset(&newmask,SIGUSR1);

23     if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0){

24         printf("sig_block error!\n");

25         exit(1);

26     }

27 

28     printf("first raise(SIGUSR1)!\n");

29     raise(SIGUSR1);

30     if(sigpending(&pendmask) < 0){

31         printf("sigpending error!\n");

32         exit(1);

33     }

34 

35     if(sigismember(&pendmask, SIGUSR1))

36         printf("sigusr1 pending!\n");

37 

38     if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0){

39         printf("sig_setmask error!\n");

40         exit(1);

41     }

42 

43     printf("second raise(SIGUSR1)!\n");

44     raise(SIGUSR1);

45 

46     printf("main end!\n");

47     exit(0);

48 }

结果如下:

【C】——sigprocmask 阻塞进程信号

如果注释掉下面的代码

1      if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0){

2          printf("sig_setmask error!\n");

3          exit(1);

4      }

结果如下:

【C】——sigprocmask 阻塞进程信号

发现第一次发送的信号也不会处理了。笔者也不知道为什么会发生这种情况,还是下次写代码的时候注意一下,阻塞完信号,处理的时候要及时恢复好了!

若只注释掉下面的代码:

1      if(sigpending(&pendmask) < 0){

2          printf("sigpending error!\n");

3          exit(1);

4      }

5  

6      if(sigismember(&pendmask, SIGUSR1))

7          printf("sigusr1 pending!\n");

而留下:

1       if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0){

2           printf("sig_setmask error!\n");

3           exit(1);

4       }

结果第一次发送的信号也会有响应,截图如下:

【C】——sigprocmask 阻塞进程信号

看来在阻塞信号的时候接收到了信号,当恢复信号屏蔽字的时候信号也会得到处理!

你可能感兴趣的:(proc)