如何实现信号屏蔽

       紧接上一篇博客,接着分享一下信号屏蔽的具体内容以及如何实现信号屏蔽。

       Linux中常见信号量只有31个,所以进程PCB中表示常见的信号量只用一个字节表示就够了,进程得到了一个信号就是对应的一个bit位由0改变为1。信号被系统发送给一个进程,就是改变PCB中表示信号量的字节中对应的一个bit位。进程收到某一信号,相当于向表示信号量的字节中写入了一个信号量。

       关于信号抵达,当信号产生后会向指定进程发送,但被发送的信号不会第一时间被抵达,进程也就不会产生相应的处理动作,所以信号存在信号未决和信号抵达这两种状态;而信号未决处于信号产生和信号抵达之间,所以,在信号抵达之前会存在一种情况叫做信号阻塞,被阻塞的信号是永远都不会在解除阻塞前被抵达的。

    Linux为了方便管理用三张表来存储这些信息。

      block表                                    表示被阻塞的信号(1为阻塞)

      pending表                                  表示未决(1为有信号未达)

      handler表                                  表示信号处理方式(有三种:忽略,默认,自定义)

    具体关系如下表:

 

    由表可以看出:

       信号1被屏蔽,虽然现在没有信号1的信号未决情况,但就算是有信号1 被发送,因为被屏蔽也不会被抵达;除非解除对信号1的屏蔽,信号1抵达后会被忽略。

       信号2没有被屏蔽,现在信号2处于信号未决情况,故信号1 最终会被抵达执行默认动作。

       信号3被屏蔽,现在信号3处于信号未决情况,因为信号3被屏蔽也就不会被抵达;除非解除对信号3的屏蔽,信号3抵达后会执行自定义动作。

    阻塞和忽略的区别:

       被阻塞的信号永远都不会被抵达,而忽略是信号被抵达的一种处理动作。

       同时需要知道的是,信号抵达后只有再合适的时机到来,才会被处理,即从内核态到用户态时。

   打印pending表并验证信号屏蔽与解除并抵达的情况。

         需要用到以下的几个函数:


源代码如下:

pending.c

  1 #include<stdio.h>
  2 #include<signal.h>
  3 #include<stdlib.h>
  4
  5 void handler1(int flag){
  6     printf("catch a signal,is num:%d\n", flag);
  7 }
  8
  9 void handler2(int flag){
 10     printf("catch a signal,is num:%d\n", flag);
 11     exit(1);
 12 }
 13
 14 void showpending(sigset_t *p){
 15     int i=1;
 16     for(; i<31; i++){
 17         if(sigismember(p,i)){
 18             printf("1");
 19         }
 20         else{
 21             printf("0");
 22         }
 23     }
 24     printf("\n");
 25 }
    27 int main(){
 28     sigset_t s,p;
 29     sigemptyset(&s);
 30     sigaddset(&s,SIGINT);
 31     printf("i block a signal:2\n");//屏蔽2号信号SIGINT
 32     sigprocmask(SIG_BLOCK,&s, NULL);
 33
 34     int i=0;
 35     while(1){
 36     signal(3,handler1);//3号信号捕捉不退出
 37     signal(20,handler1);//20号信号捕捉不退出
 38     signal(2,handler2);//2号信号捕捉并退出
 39     sigpending(&p);
 40     showpending(&p);
 41     sleep(1);
 42     i++;
 43     if(i == 10){
 44         printf("i will unblock a signal:2\n");
 45         sigprocmask(SIG_UNBLOCK,&s, NULL);//i等于10时,解除对2号信号SIGINT的屏蔽
 
 46      }
 47     }
 48     return 0;
 49 }

Makefile

 

运行结果如下

 

      想知道为何这样运行,可以去看一看源代码,不多解释了。

    分享如上,望共同进步!

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值