linux之信号屏蔽pending

一、信号的三种表示:

1)信号递达(Delivery):实际执行信号的处理动作
2)信号未决(Pending):信号从产生到递达之间的状态
3)进程可以选择阻塞(Block )某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才 执行递达的动作。
注:阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后 可选的⼀种处理动作。

二、信号在内存中的表示图
这里写图片描述
每个信号都有两个标志位,表示阻塞和未决,handler表示处理信号的动作(默认、忽略和自定义)。

三、信号集
sigset_t称为信号集,用来表示信号的有效或无效状态,用0、1表示
(1)阻塞信号集:该信号是否被阻塞 ,阻塞信号集也叫做当前进程的信号屏蔽字
(2)未决信号集:当前信号是否处于未决状态。

信号集操作函数:

int sigemptyset(sigset_t *set); 
初始化set所指向的信号集,使其中所有信号的对应bit清零,表⽰该信号集不包含 任何有效信号。

int sigfillset(sigset_t *set); 
初始化set所指向的信号集,使其中所有信号的对应bit1,表⽰ 该信号集的有效信号包括系统⽀持的所有信号。

int sigaddset(sigset_t *set, int signo); 
添加有效信号

int sigdelset(sigset_t *set, int signo); 
删除有效信号

int sigismember(const sigset_t *set, int signo); 
sigismember是⼀个布尔函数,⽤于判断⼀个信号集的有效信号中是否包含某种 信号,若包含则返回1,不包含则返回0,出错返回-1。

sigprocmask函数用来读取或更改进程的阻塞信号集

int sigprocmask(int how, const sigset_t *set, sigset_t *oset) 
成功返回0,出错为-1

若oset非空,则读取当前进程的阻塞信号集
若set非空,则更改当前进程的阻塞信号集,how用来指示如何修改
若两者都非空,则将原来的信号屏蔽字备份到oset中,然后根据set、how修改

how指示当前的信号屏蔽字如何修改,下面对how作以解释,以mask为例
这里写图片描述

如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达。
sigpending用来读取当前信号的未决信号集
int sigpending(sigset_t *set);
成功返回0,出错返回-1

四,代码实现

(1)实现信号的屏蔽

#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void showpending(sigset_t *pending)
 {
     int i = 0;
     for( ; i <= 31; i++)
     {
        if(sigismember(pending,i)) //判断是否包含某个信号
            printf("1"); 
        else
            printf("0");
     }
     printf("\n");
 }

  int main()
  {
     sigset_t blockSet,oblockSet,pending; 
     sigemptyset(&blockSet);  //清空信号集
     sigemptyset(&oblockSet);
     sigaddset(&blockSet,2); //添加2号信号Ctrl+c
     sigprocmask(SIG_SETMASK, &blockSet, &oblockSet); //阻塞2号信号

     while(1)
     {
        sigpending(&pending); //读取未决信号集
        showpending(&pending); //显示未决信号集
        sleep(1);
     }
  }

这里写图片描述

(2)实现信号的屏蔽与解除并递达(单次)

这里写图片描述
结果如下:
这里写图片描述

(3)信号的屏蔽与解除并递达(多次实现)

#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void handler(int sig)
{
   printf("get a sig:%d\n",sig);
}

void showpending(sigset_t *pending)
{
   int i = 0;
   for( ; i <= 31; i++)
   {   
      if(sigismember(pending,i))
          printf("1");
      else
          printf("0");
   }   
   printf("\n");
}

int main()
{
   sigset_t blockSet,oblockSet,pending;
   sigemptyset(&blockSet);
   sigemptyset(&oblockSet);
   sigaddset(&blockSet,2);
    while(1) //添加while循环,使信号可以被屏蔽多次
    {   
       signal(2,handler);
       sigprocmask(SIG_SETMASK,&blockSet,&oblockSet);
       int count=1;
       while(1)
       {   
           sigpending(&pending);
           showpending(&pending);
           sleep(1);
           if(count++==10)
           {   
               printf("recover proc block set\n");
               sigprocmask(SIG_SETMASK,&oblockSet,NULL);
               break; //跳出循环
           }   
       }   
    }   
}

结果如下:

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值