目录
一.信号集操作函数
sigpromask函数
代码详解:
编辑
考虑情况一:对多个信号的屏蔽
考虑情况二:取消对信号的阻塞
运行结果:
考虑情况三:若不想让进程退出,采用自定义捕捉信号方式!
完整代码:
一.信号集操作函数
sigset_t类型对于每种信号用一个bit表示“有效”或“无效”状态,至于这个类型内部如何存储这些bit则依赖于系统实现,从使用者的角度是不必关心的,使用者只能调用以下函数来操作sigset_t变量而不应该对它的内部数据做任何解释,比如用printf直接打印sigset_t变量是没有意义的。
sigpromask函数
格式:int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
第一参数how : 告诉sigprocmask函数,应该做什么操作:
SIG BLOCK: 设置某个信号为阻塞
SIG UNBLOCK:接触对某个信号的阻塞
SIG SETMASK: 替换阻寒位图
第二参数set:用来设置阻塞位图;
第三参数oldset:原来的阻塞位图sigpromask的第一参数大多情况下用的是SIG_SETMASK方式,用一个位图替换另一个位图
代码详解:
第一步:使用sigset_t类型创建位图结构; 第二步:初始化位图;
第三步:给阻塞位图添加信号; 第四步:将block阻塞位图设置为最终的阻塞位图
第五步:获取未决位图pending的数据信息。
第六步:自定义函数打印未决位图——利用遍历方式,将未决位图的每一比特位进行遍历打印输出。
注:阻塞信号情况是信号未决的一个分支情况!
考虑情况一:对多个信号的屏蔽
该情况下,使用了vector容器,将想要阻塞的信号写入容器中,使用auto遍历方式给阻塞位图添加多个信号。
运行结果:
考虑情况二:取消对信号的阻塞
运行结果:
为什么信号取消了阻塞,进程就停止了 ?
原因: 因为2,3号信号本就是进程中断信号,信号取消阻塞,导致进程对该信号进行递达操作(默认一立即退出)
想要取消对指定信号的阻塞,可以使用oblock代替block位图
考虑情况三:若不想让进程退出,采用自定义捕捉信号方式!
运行结果:
完整代码:
#include<iostream>
#include<signal.h>
#include<vector>
#include<unistd.h>
//打印未决位图
void Print(const sigset_t& pend){
for(int i=31;i>=1;--i){
if(sigismember(&pend,i)){
std::cout<<"1";
}
else{
std::cout<<"0";
}
}
std::cout<<std::endl;
}
void handler(int signo){
std::cout<<"已捕获信号:"<<signo<<std::endl;
}
int main(){
sigset_t pending,block,oblock; //创建三个位图,一个为未决,两个为阻塞位图,
sigemptyset(&pending);
sigemptyset(&block);
sigemptyset(&oblock);
//给阻塞位图添加信号
std::vector<int> v1;
v1.push_back(2);
v1.push_back(3);
for(auto e:v1){
sigaddset(&block,e);
signal(e,handler);
}
//屏蔽信号
sigprocmask(SIG_SETMASK,&block,&oblock);//block位图代替了oblock位图
int cnt=1;
while(cnt){
sigpending(&pending); //读取未决位图信息
Print(pending); //打印未决位图
sleep(1);
++cnt;
if(cnt==8){
//取消屏蔽
sigprocmask(SIG_SETMASK,&oblock,&block);
}
}
return 0;
}