信号的保存
一.信号保存方式
1.保存原理
信号保存原理其实在上篇信号(一)中,提到过保存的原理
我们linux中的信号
一共是1-31位,正好用32位大小的int整形来表示
原理其实就是这样
但是实际上肯定不是这么简单的,所以这篇博客就是来稍微深入了解下,Linux中的信号的保存形式
2.三表
Linux信号保存主要就是三个位图表
这里我们分别一个一个来讲作用
i.block
block表
这个表的作用是来设置信号屏蔽/阻塞
什么叫信号屏蔽/阻塞
就是当2信号在block表中被置1时,表示2信号被屏蔽
这个时候2信号不会被传递给进程
同时告诉系统,暂时不要处理这个号码的信号
Block表相当于是把这些信号暂时拉入了黑名单,
在OS传递给进程之前,就被拦了下来
ii.pending
这个表的是来记录信号是否被阻碍执行了
比如:
当block中有个2信号被屏蔽,然后系统发送了2信号
这个时候就会把pending中的2信号给置1,表示信号2发送过来,但被拦截了
因为屏蔽和是否发送是两回事
你是否屏蔽它,和它是否发送没有什么关系
Block就是告诉系统,暂时不要处理这个信号,但是发送的所以pending主要是记录待处理信息,你屏蔽到最后,还是要去执行这个信号的,所以说还是要再pending表中,把Block表中屏蔽的信号收到,也置为一
iii.handler
这个表本质是一个函数指针数组,记录了每个信号对应处理方法
二.信号保存设置接口
!!!改变方式!!!
我们了解基本的保存机制了
接下来就是使用接口了
首先我们要了解一点
操作系统从从来不信任用户
所以我们不能直接去改变系统中的这三个表
最后还是要通过:
系统允许你用的接口去调用改变
这里我们来了解一下block表的改变方法
大致就是这样,接下来来了解各个接口和具体过程
1.共同接口和变量
i.sigset_t
系统给你定义的类型,用来传递给位图改值的
ii.sigemptyset()
这个作用是把sigset_t里面清空置0
iii.sigaddset()
这个接口的作用是:
将位图set中的第signum个的信号置为一
2.三表设置接口
接下来就是改变三个表的接口了
三个表,分别由三个对应的接口,调用和改变
i.sigprocmask()
具体用法:
ii.sigpending()
我们知道pending本质上就是记录是否信号被拦截的的一个表
所以说我们没必要去改变什么
这个接口就是让我们去获取系统的pending表
iii.signal()
这个再前面一篇博客上讲过,可以去那边看看——信号【上】
3.使用实例
#include <signal.h>
#include<iostream>
void printpending(sigset_t & pend)
{
for(int signo=31;signo>=1;signo--)
{
if(sigismember(&pend,signo))
{
std::cout<<"1";
}
else
{
std::cout<<"0";
}
}
std::cout<<"\n\n";
}
int main()
{
sigset_t s1;
sigemptyset(&s1);
sigaddset(&s1,2);
sigprocmask(SIG_SETMASK,&s1,nullptr);
while(true)
{
sigset_t pend;
int n=sigpending(&pend);
if(n<0)
{
continue;
}
printpending(pend);
sleep(1);
}
}
这里
1.把CTRL+C的2信号放进了block
2.不停打印pending表,查看拦截信号
3.发送CRTL+C表,查看是否被屏蔽和拦截