十_信号8 - sigprocmask() 设置信号集当中信号的mask信号屏蔽字

sigprocmask() :虽然我不知道信号什么时候来,但是我可以决定 什么时候响应信号

信号屏蔽字处理

在这里插入图片描述

sigprocmask(); // 控制 信号相应过程中的 mask位图,mask 位图 用来标记是否响应各个信号,1为响应 0为忽略

对 set信号集中的所有信号 作 how 动作操作,oldset保留的是 对该信号集操作之前的 信号集中信号的状态

SIG_BLOCK 对目标信号集中的所有信号进行阻塞,即将mask信号屏蔽位置0
SIG_UNBLOCK 对目标信号集中的所有信号解除阻塞 即将mask信号屏蔽位置1
SIG_SETMASK 回复信号集之前的状态,并保存信号集恢复之前的当前状态

实验:
每秒向标准输出打印一个* 打印五秒换行。程序不受 CTRL+C 即 SIGINT信号影响,收到 SIGINT信号 响应信号 打印!。

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

void sig_handler(int s)
{
	write(1,"!",1);
}

int main()
{
	int i,j;

	signal(SIGINT,sig_handler);
	for(j=0;j < 1000;j++)
	{

		for(i=0 ; i<5 ; i++)
		{
			write(1,"*",1);
			sleep(1);
		}	
		write(1,"\n",1);
	}


	exit(0);
}

修改: sigprocmask(SIG_BLOCK…)+ sigprocmask(SIG_UNBLOCK…)
只在两行*之间输出 !, 即 选择响应 SIGINT 信号的时间。

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


void sig_handler(int s)
{
	write(1,"!",1);
}

int main()
{
	int i,j;
	sigset_t set;//创建信号集

	signal(SIGINT,sig_handler);
	
	sigemptyset(&set); //清空信号集
	sigaddset(&set,SIGINT); // 添加 SIGINT信号 到信号集


	for(j=0;j < 1000;j++)
	{

		sigprocmask(SIG_BLOCK,&set,NULL); // 对 set信号集中的信号 进行阻塞,即将mask信号屏蔽位置0
		for(i=0 ; i<5 ; i++) 
		{
			write(1,"*",1);
			sleep(1);
		}	
		write(1,"\n",1);
		sigprocmask(SIG_UNBLOCK,&set,NULL); // 对 set信号集中的信号 解除阻塞,即将mask信号屏蔽位置1
	}


	exit(0);
}


mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ gcc sigprocmask.c 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ ./a.out 
***^C*^C*^C^C^C^C^C
!*^C^C^C^C^C^C*^C^C^C^C^C^C*^C**
!*****
*^C*^C^C^C^C^C*^C^C*^C*
!*****
*****
*****
*****
*****
****^C*^C
!***^C^C**
!*****^\Quit (core dumped)
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ 

注意:两次sigprocmask之间

sigprocmask(SIG_BLOCK,&set,NULL);

注意1
这之间 已经屏蔽了 SIGINT 信号,即将SIGINT 的mask信号屏蔽位置0,所以就算有信号来,mask信号屏蔽位 按位与 pending信号状态位,结果也是0,所以不响应 SIGINT信号的动作,即不打印!

注意2
只有解除 SIGINT 信号阻塞,即将mask信号屏蔽位置1,并赶上 程序从内核态切换回用户态的时候 才会计算mask信号屏蔽位 按位与 pending信号状态位 的结果,并响应SIGINT 信号动作,即 打印!

注意3
而且 不论 发送多少个 SIGINT 信号,只会打印一个 !,即只会响应一次信号。这就是之前 在 信号的响应过程 中说的 标准信号为什么要丢失 这个问题了,信号的响应过程那篇文章很关键,信号的响应过程那篇文章很关键,信号的响应过程那篇文章很关键,信号的响应过程那篇文章很关键,信号的响应过程那篇文章很关键


sigprocmask(SIG_UNBLOCK,&set,NULL);

并且 还有一点很重要,发现实验中 SIGINT 信号 也不会打断阻塞的系统调用了。只有 SIG_BLOCK 之后才会,原因同上,因为已经屏蔽了该信号。

修改: sigprocmask(SIG_BLOCK…)+ sigprocmask(SIG_SETMASK …)

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


void sig_handler(int s)
{
	write(1,"!",1);
}

int main()
{
	int i,j;
	sigset_t set,oset;//创建信号集

	signal(SIGINT,sig_handler);
	
	sigemptyset(&set); //清空信号集
	sigaddset(&set,SIGINT); // 添加 SIGINT信号 到信号集


	for(j=0;j < 1000;j++)
	{

// 对 set信号集中的信号 进行阻塞,即将mask信号屏蔽位置0. 并且将 信号集阻塞之前的状态保存到 oset
		sigprocmask(SIG_BLOCK,&set,&oset); 
		for(i=0 ; i<5 ; i++) 
		{
			write(1,"*",1);
			sleep(1);
		}	
		write(1,"\n",1);

//即 恢复 oset信号集,即解除阻塞
		sigprocmask(SIG_SETMASK,&oset,NULL); 
	}


	exit(0);
}


mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ gcc sigprocmask.c 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ ./a.out 
***^C*^C*^C^C^C^C^C
!*^C^C^C^C^C^C*^C^C^C^C^C^C*^C**
!*****
*^C*^C^C^C^C^C*^C^C*^C*
!*****
*****
*****
*****
*****
****^C*^C
!***^C^C**
!*****^\Quit (core dumped)
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ 

结果一样
通常的做法是:一定要保存和回复 修改之前的信号集状态

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


void sig_handler(int s)
{
	write(1,"!",1);
}

int main()
{
	int i,j;
	sigset_t set,saveset;//创建信号集

	signal(SIGINT,sig_handler);
	
	sigemptyset(&set); //清空信号集
	sigaddset(&set,SIGINT); // 添加 SIGINT信号 到信号集

//在当前模块修改之前 保存信号集状态,以便 当前模块执行完成后恢复 信号集状态
sigprocmask(SIG_UNBLOCK,&set,&saveset);

	for(j=0;j < 1000;j++)
	{

		sigprocmask(SIG_BLOCK,&set,NULL); // 对 set信号集中的信号 进行阻塞,即将mask信号屏蔽位置0
		for(i=0 ; i<5 ; i++) 
		{
			write(1,"*",1);
			sleep(1);
		}	
		write(1,"\n",1);
		sigprocmask(SIG_UNBLOCK,&set,NULL); // 对 set信号集中的信号 解除阻塞,即将mask信号屏蔽位置1
	}

// 恢复 之前信号集状态
sigprocmask(SIG_SETMASK,&saveset,NULL);

	exit(0);
}

在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux老A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值