信号集操作函数

内核通过读取未决信号集来判断信号是否应被处理。信号屏蔽字mask可以影响未决信号集。而我们可以在应用程序中自定义set来改变mask。已达到屏蔽指定信号的目的。综上:自定义信号集set(也为一个字,64位)通过信号集操作函数来改变信号屏蔽字mask,然后mask进一步来影响未决信号集,从而控制信号是否应该被屏蔽。后面我们只是研究常规信号,即1~31号!

1)信号集的设置

sigset_t  set;         // typedef unsigned long sigset_t;  声明一个信号集变量set,信号集类型为sigset_t,为unsigned long(无符号长整型),64位。

int sigemptyset(sigset_t *set);       //将set所指信号集清0        成功:0;失败:-1

int sigfillset(sigset_t *set);            //将set所指信号集置1        成功:0;失败:-1

int sigaddset(sigset_t *set, int signum);        //将某个信号加入信号集(即将其置1)  成功:0;失败:-1

int sigdelset(sigset_t *set, int signum);         //将某个信号清出信号集(即将其置0)  成功:0;失败:-1

int sigismember(const sigset_t *set, int signum); 判断某个信号是否在信号集中(是否为1)返回值:在集合:1;不在:0;出错:-1 

sigset_t类型的本质是位图。但不应该直接使用位操作,而应该使用上述函数,保证跨系统操作有效。

对比认知select 函数。

2sigprocmask函数

用来屏蔽信号或解除屏蔽,即用于读取和修改进程的信号屏蔽字mask。在用户设置好自己的信号集set后,通过sigprocmask函数,可以利用set来对mask进行修改,以实现屏蔽和解除屏蔽的目的。

注意:屏蔽信号只是将信号处理延后执行(延至解除屏蔽);而忽略表示将信号丢弃处理。

 

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);   

返回值: 成功:0;失败:-1,设置errno

参数how1.SIG_BLOCK: 当how设置为此值,set表示需要屏蔽的信号。相当于 mask = mask|set,即将set中为1的信号添加到mask中,mask中原有的信号不变;2.SIG_UNBLOCK: 当how设置为此,set表示需要解除屏蔽的信号。相当于 mask = mask & ~set(先对set位取反,再位与操作),即将set中为1的信号对应的mask中将其置为0(解除屏蔽),其余信号不变;3.SIG_SETMASK:当how设置为此,set表示用于替代mask的新屏蔽集。相当于 mask = set。调用sigprocmask解除了对当前若干个信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达。

参数set传入参数,是一个位图,自己设置。

参数oldset传出参数,保存旧的信号屏蔽集,即在该函数对mask处理前的mask的值。 如果不关心上一次的屏蔽字mask是什么,第三个参数可以设为NULL

3sigpending函数

作用:读取当前进程的未决信号集

int sigpending(sigset_t *set);   set传出参数。   返回值:成功:0;失败:-1,设置errno

 

//练习:编写程序。把所有常规信号的未决状态打印至屏幕。     

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>void printset(sigset_t *ped)  //打印出ped所指信号集的前1~31位(常规信号)
{int i;for(i = 1; i < 32; i++){if( (sigismember(ped, i) == 1) ){putchar('1');     //标准输出} else if( (sigismember(ped, i) == 0) ) {putchar('0');} else {perror( “sigismember”);exit(1);}}printf("\n");
}int main(void)
{sigset_t set, ped;
#if 0   sigemptyset(&set);   //清0sigaddset(&set, SIGINT);   //加入2号信号sigaddset(&set, SIGQUIT);   //加入3号信号sigaddset(&set, SIGKILL);  //加入9号信号,记住其不可以被阻塞、忽略和捕捉sigaddset(&set, SIGSEGV);  //加入11号信号
#endifsigfillset(&set);    //全部置1,则所有信号全部设置为阻塞sigprocmask(SIG_BLOCK, &set, NULL);     //不获取原屏蔽字while(1){sigpending(&ped);       //获取未决信号集printset(&ped);sleep(1);}return 0;
}

[root@localhost 01_signal_test]# ./sigpending

0000000000000000000000000000000

0000000000000000000000000000000

^Z0000000000000000000100000000000  //Ctrl +Z  20号信号

^C0100000000000000000100000000000  //Ctrl +C  2号信号

^\0110000000000000000100000000000   //Ctrl +\   3号信号

0110000000000000000100000000000   

0110000000000000000100000000000

0110000000000000000100000000000

0110000000100000000100000000000  //  [root@localhost ~]# kill -11 5710

 

通过以上可以看出:发送的信号全部被阻塞,在未决信号集中都置为1。最后发送9号信号,杀死该进程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/385329.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信号捕捉(signal、sigaction)

信号的基本属性&#xff1a;软中断&#xff0c;由内核发送&#xff0c;内核处理。某个进程通过内核向另一个进程发送信号时&#xff08;引起信号产生的五个因素&#xff09;&#xff0c;另一个进程将会陷入内核进行中断处理&#xff0c;未决信号集中相应信号置1&#xff0c;当递…

1090 Highest Price in Supply Chain (25)(25 分)

A supply chain is a network of retailers&#xff08;零售商&#xff09;, distributors&#xff08;经销商&#xff09;, and suppliers&#xff08;供应商&#xff09;-- everyone involved in moving a product from supplier to customer. Starting from one root suppli…

时序竞态(竞态条件)

产生原因&#xff1a;仍然以前文实现的sleep函数为例&#xff0c;如果进程在执行完alarm函数后&#xff0c;突然失去CPU&#xff0c;被阻塞等待&#xff08;这是有可能的&#xff0c;进程在执行过程中&#xff0c;若非原子操作&#xff0c;都有可能随时失去CPU&#xff09;&…

1106 Lowest Price in Supply Chain (25)

A supply chain is a network of retailers&#xff08;零售商&#xff09;, distributors&#xff08;经销商&#xff09;, and suppliers&#xff08;供应商&#xff09;-- everyone involved in moving a product from supplier to customer. Starting from one root suppli…

【Leetcode | 顺序刷题 】二分查找目录

二分查找序号题号129. 两数相除 50. Pow(x, n) 69. x 的平方根

sigsuspend函数(mysleep函数的改进)

可以通过设置屏蔽SIGALRM的方法来控制程序执行逻辑&#xff0c;但无论如何设置&#xff0c;程序都有可能在“解除信号屏蔽”与“挂起等待信号”这个两个操作间隙失去cpu资源。除非将这两步骤合并成一个“原子操作”。sigsuspend函数具备这个功能。在对时序要求严格的场合下都应…

【Leetcode | 顺序刷题】数学目录

序号题号1 7. 整数反转 28. 字符串转换整数 (atoi)39. 回文数443. 字符串相乘

全局变量的异步I/O问题

全局变量的异步I/O问题同样属于时序竞态问题&#xff0c;其本质就是多个进程或者同一个进程中的多个时序&#xff08;如主控程序和信号捕捉时的用户处理函数&#xff09;对同一个变量进行修改时&#xff0c;它们的执行顺序不一样就会导致该变量最终的值不一样&#xff0c;从而产…

【Leetcode | 03】String

字符串目录序号题号33. 无重复字符的最长子串 151. 翻转字符串里的单词

可/不可重入函数

一个函数在被调用执行期间&#xff08;尚未调用结束&#xff09;&#xff0c;由于某种时序&#xff08;递归或者处理信号捕捉时等情况&#xff09;又被重复调用&#xff0c;称之为“重入”。根据函数实现的方法可分为“可重入函数”和“不可重入函数”两种。看如下程序。 可以看…

【Leetcode | 顺序刷题】杂项目录

序号题号类别1136. 只出现一次的数字位运算2137. 只出现一次的数字 II位运算3 260. 只出现一次的数字 III 位运算4191. 位1的个数位运算5231. 2的幂位运算6342. 4的幂位运算7 338. 比特位计数 位运算8405. 数字转换为十六进制数位运算9371. 两整数之和位运算10401. 二进制手表位…

SIGCHLD信号

&#xff08;1&#xff09;SIGCHLD信号产生的条件 1.子进程终止时会向父进程发送SIGCHLD信号&#xff0c;告知父进程回收自己&#xff0c;但该信号的默认处理动作为忽略&#xff0c;因此父进程仍然不会去回收子进程&#xff0c;需要捕捉处理实现子进程的回收&#xff1b; 2.子…

信号传参

&#xff08;1&#xff09;发送信号传参 前面已经知道从一个进程向另一个进程发送信号可以使用kill函数&#xff0c;但是kill函数在向进程发送信号的时候不能携带除了信号以外的其他信息&#xff0c;这时可以使用与kill相对应的sigqueue函数&#xff0c;该函数也是向一个进程发…

【Leetcode | 52】257. 二叉树的所有路径

给定一个二叉树&#xff0c;返回所有从根节点到叶子节点的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 输入: 1 / \ 2 3 \ 5 输出: ["1->2->5", "1->3"] 解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3 解法一&a…

623. 在二叉树中增加一行

给定一个二叉树&#xff0c;根节点为第1层&#xff0c;深度为 1。在其第 d 层追加一行值为 v 的节点。 添加规则&#xff1a;给定一个深度值 d &#xff08;正整数&#xff09;&#xff0c;针对深度为 d-1 层的每一非空节点 N&#xff0c;为 N 创建两个值为 v 的左子树和右子树…

终端的概念

操作系统接口&#xff1a;用户接口和程序接口。用户接口分为联机用户接口和脱机用户接口。脱机用户接口出现在早期的批处理系统中&#xff08;将作业提前交给操作系统&#xff0c;作业完成的过程中用户无法交互&#xff09;&#xff1b;联机用户接口即为终端&#xff08;所有输…

终端的启动流程

在Linux操作系统启动时&#xff0c;首先加载的进程就是init进程&#xff08;ID为1&#xff09;&#xff0c;其余进程都是init进程产生的&#xff08;fork&#xff0c;然后exec金蝉脱壳&#xff09;&#xff0c;因此系统中所有进程都可以看成是init进程的子孙进程。可以通过ps a…

进程组(作业)

&#xff08;1&#xff09;概念和特性 进程组&#xff0c;也称之为作业。BSD于1980年前后向Unix中增加的一个新特性。代表一个或多个进程的集合。每个进程都属于一个进程组。在waitpid函数和kill函数的参数中都曾使用到。操作系统设计的进程组的概念&#xff0c;是为了简化对多…

437. 路径总和 III

给定一个二叉树&#xff0c;它的每个结点都存放着一个整数值。 找出路径和等于给定数值的路径总数。 路径不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff0c;但是路径方向必须是向下的&#xff08;只能从父节点到子节点&#xff09;。 二叉树不超过1000个节…

会话(session)

一组进程形成一个进程组&#xff0c;一组进程组形成一个会话&#xff0c;即一个会话中可以包括多个进程组。 &#xff08;1&#xff09;创建会话 创建一个会话需要注意以下6点注意事项&#xff1a;1.调用进程不能是进程组组长&#xff08;不能是父进程&#xff09;&#xff0…