函数sigsetjump和siglongjump

摘要:

  • 在信号处理函数执行时,会阻塞当前信号。
  • 当信号处理函数返回时,系统会帮我们把刚刚阻塞的信号再从阻塞集中移除。

 

一、 临时阻塞特性

当执行信号处理函数的时候,会临时将当前被处理信号阻塞。为了能说明问题,采用实验来验证。

下面这段程序在收到 SIGALRM 信号或者 SIGQUIT 信号时,会打印当前信号,同时打印当前被阻塞的信号。

测试代码:

#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>void printBlock() {sigset_t block;sigprocmask(SIG_BLOCK, NULL, &block);printf("block:");if (sigismember(&block, SIGQUIT)) printf("SIGQUIT, ");if (sigismember(&block, SIGALRM)) printf("SIGALRM\t");puts("");
}void handler(int sig) {if (sig == SIGQUIT) printf("SIGQUIT, ");if (sig == SIGALRM) printf("SIGALRM, ");printBlock();puts("--------------------------------------------------");
}int main() {printf("I'm %d\n", getpid());signal(SIGQUIT, handler);signal(SIGALRM, handler);printf("before signal, ");printBlock();while (1) {pause();}return 0;
}

输出结果:

结果分析:

可以看到当程序收到 SIGALRM 信号时,在信号处理函数中 SIGALRM 信号会被临时阻塞;SIGQUIT 信号同理。

执行完毕再从阻塞信号集中移除我就不验证了。实际上,你重复发送 SIGALRM 信号,信号处理函数都能正常执行就已经证明 SIGALRM 信号未被阻塞(当然了,如果你手速比 cpu 运行的还快,可能会有信号合并的情况,这种不在考虑之列)。
 

 

 

二、跳出你的信号处理函数 

试想一下,如果你在信号处理函数中使用 longjmp 跳走了,系统会不会帮你把临时阻塞的信号给撤走?答案是,不会。这将导致程序 bug。从此以后,你的程序再也不能处理该信号了。空口无凭,用实验说话。

下面这段程序,在信号处理函数中打印当前信号和当前被阻塞的信号。完成后没有直接 return,而是使用 longjmp 跳转到 setjmp 的位置。接下来再打印阻塞信号。

测试代码:

#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>jmp_buf jmpbuf;void printBlock()
{sigset_t block;sigprocmask(SIG_BLOCK, NULL, &block);printf("block:");if (sigismember(&block, SIGQUIT)) printf("SIGQUIT, ");if (sigismember(&block, SIGALRM)) printf("SIGALRM");puts("");
}void handler(int sig)
{if (sig == SIGQUIT) printf("SIGQUIT, ");if (sig == SIGALRM) printf("SIGALRM, ");printBlock();longjmp(jmpbuf, 1);puts("--------------------------------------------------");
}int main()
{printf("I'm %d\n", getpid());signal(SIGQUIT, handler);signal(SIGALRM, handler);printf("before signal, ");printBlock();if (setjmp(jmpbuf) != 0) {printf("jump to here! ");printBlock();puts("====================================================");}while (1) {pause();}return 0;
}

 输出结果:

结果分析:

可以看到,当 jump 到 main 函数中的时候,SIGQUIT 依然被阻塞了,SIGALRM 也是。此后,无论你再怎么发送这两个信号,处理函数也不会执行了。因为这两个信号没有从阻塞集中删除。

这是 bug。

解决方案是使用另外两个函数,分别是 sigsetjmp 和 siglongjmp。所以,我们只要把上面代码中的 setjmp 和 longjmp 分别替换成这两个函数就行了。
 

 

三、函数sigsetjump和siglongjump应用

1. 测试代码:

#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>jmp_buf jmpbuf;void printBlock() {sigset_t block;sigprocmask(SIG_BLOCK, NULL, &block);printf("block:");if (sigismember(&block, SIGQUIT)) printf("SIGQUIT, ");if (sigismember(&block, SIGALRM)) printf("SIGALRM");puts("");
}void handler(int sig) {if (sig == SIGQUIT) printf("SIGQUIT, ");if (sig == SIGALRM) printf("SIGALRM, ");printBlock();siglongjmp(jmpbuf, 1); puts("--------------------------------------------------");
}int main() {printf("I'm %d\n", getpid());signal(SIGQUIT, handler);signal(SIGALRM, handler);printf("before signal, ");printBlock();if (sigsetjmp(jmpbuf, 1) != 0) {printf("jump to here! ");printBlock();puts("====================================================");}while(1) {pause();}return 0;
}

输出结果: 

 

四、参考资料 

1. 47-跳出信号处理函数

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

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

相关文章

java操作word文档,深度解析,值得收藏

Java虚拟机内存模型 Java虚拟机内存模型中定义的访问操作与物理计算机处理的基本一致&#xff01; Java中通过多线程机制使得多个任务同时执行处理&#xff0c;所有的线程共享JVM内存区域main memory&#xff0c;而每个线程又单独的有自己的工作内存&#xff0c;当线程与内存区…

java支付模块架构,涨薪7K!

Java基础 JDK 和 JRE 有什么区别&#xff1f; 和 equals 的区别是什么&#xff1f;两个对象的 hashCode()相同&#xff0c;则 equals()也一定为 true&#xff0c;对吗&#xff1f;final 在 java 中有什么作用&#xff1f;java 中的 Math.round(-1.5) 等于多少&#xff1f;Stri…

【信号】SIGCHLD信号

一、SIGCHLD信号 1. SIGCHLD简介 SIGCHLD的产生条件&#xff1a; 子进程终止子进程接收到SIGSTOP信号停止时子进程处于停止状态&#xff0c;接收到SIGCONT后唤醒注意&#xff1a;通过signal(SIGCHLD, SIG_IGN)通知内核对子进程的结束不关心&#xff0c;由内核回收。如果不想让…

java改错题技巧,看这篇文章准没错!

阿里 mq 消息可靠性,幂等如何保证分布式锁的实现方案比较,为什么选择 zookeeper, zookeeper 一致性协议原理线程池参数,阻塞队列实现一致性 Hash解决什么问题, 如何实现? 虚拟节点的作用?Java 锁的实现方式, 比较? AQS实现原理?公平非公平实现原理?CAS 实现原理volatile 实…

函数stat、fstat、fstatat和lstat

一、主要函数应用 #include <sys/stat.h> int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf) int lstat(const char *path, struct stat *buf); int fstat(int fd, const char *path, struct stat *buf, int flag);参数&#xff1a;…

java教程pdf下载百度云,面试题+笔记+项目实战

一面问题&#xff1a;MySQLRedisKafka线程算法 mysql知道哪些存储引擎&#xff0c;它们的区别mysql索引在什么情况下会失效mysql在项目中的优化场景&#xff0c;慢查询解决等mysql有什么索引&#xff0c;索引模型是什么B-树与B树的区别&#xff1f;为什么不用红黑树mysql主从同…

函数mkdir、mkdirat和emdir

一、目录的权限位 目录的权限位&#xff0c;至少要设置一个执行许可位。即 rwx 中的那个 x 位。如果不设置&#xff0c;就没办法使用 cd 命令进入目录&#xff0c;也无法读取目录下的文件内容。所以&#xff0c;这个位是必须的。目录的写权限位。如果未设置写权限位(w 位)&…

java教程传智播客,面试真题解析

01 阿里中间件&#xff08;四面&#xff0c;Java岗&#xff09; 1.1 Java中间件一面 技术一面考察范围 重点问了Java线程锁&#xff1a;synchronized 和ReentrantLock相关的底层实现 线程池的底层实现以及常见的参数 数据结构基本都问了一遍&#xff1a;链表、队列等 Java内存…

java教程百度文库,成功拿到offer

正文 现在市面上的算法资料也五花八门&#xff0c;种类繁多&#xff0c;小编也整理了一份不同于市面且有意思的算法资料&#xff0c;不能说多全面&#xff0c;但是是小编花了很长时间整理归纳出来的&#xff0c;自我感觉还行。分享给同事及群里反响都不错&#xff0c;所以小编…

java数字排序代码,进阶加薪全靠它!

数据库 2.1 池化技术&#xff1a;如何减少频繁创建数据库连接的性能损耗&#xff1f;2.2 数据库优化方案&#xff08;一&#xff09;&#xff1a;查询请求增加时&#xff0c;如何做主从分离&#xff1f;2.3 数据库优化方案&#xff08;二&#xff09;&#xff1a;写入数据量增…

函数umask

umask函数原型&#xff1a; #include <sys/stat.h> mode_t umask(mode_t mask); 分析&#xff1a; 在进程创建一个新的文件或目录时&#xff0c;如调用open函数创建一个新文件&#xff0c;新文件的实际存取权限是mode与umask按照 mode&~umask运算以后的结果。umask…

java数据分析库,威力加强版

美团技术一面20分钟 晚7点&#xff0c;因为想到下周一才面试&#xff0c;我刚准备出去打个羽毛球&#xff0c;北京的电话就来了。面试官各种抱歉&#xff0c;说开会拖延了。 1、自我介绍 说了很多遍了&#xff0c;很流畅捡重点介绍完。 2、问我数据结构算法好不好 挺好的&…

函数chown

一、chown 命令 下面以实例简单讲解下 chown 的使用方法。当前登录的账号是 sunbin 创建测试文件当前 test.txt 文件所有者是sunbin&#xff0c;所属组也是sunbin。 利用 chown 命令修改 test.txt 的所有者和所属组.可以看到&#xff0c;test.txt 的拥有者变成了 root&#…

不愧是Alibaba技术官,java数组实现单向链表

缓存雪崩 缓存雪崩指的是Redis当中的大量缓存在同一时间全部失效&#xff0c;而假如恰巧这一段时间同时又有大量请求被发起&#xff0c;那么就会造成请求直接访问到数据库&#xff0c;可能会把数据库冲垮。 缓存雪崩一般形容的是缓存中没有而数据库中有的数据&#xff0c;而因…

【线程】读写锁

一、概念 一把读写锁具备三种状态&#xff1a; 读模式下加锁状态(读锁&#xff09;写模式下加锁转态(写锁)不加锁状态2. 读写锁特性&#xff1a; 读写锁是写模式加锁时&#xff0c;解锁前&#xff0c;所有对该锁加锁的线程都会阻塞。读写锁是读模式加锁时&#xff0c;如果线程以…

不愧是阿里大佬,mysql存储过程写法案例

容器化时代来了 虚拟化技术已经走过了三个时代&#xff0c;没有容器化技术的演进就不会有 Docker 技术的诞生。 虚拟化技术演进 &#xff08;1&#xff09;物理机时代&#xff1a;多个应用程序可能会跑在一台机器上。 &#xff08;2&#xff09;虚拟机时代&#xff1a;一台物…

不看绝对血亏!java字符串转json

一、对Kafka的认识 1.Kafka的基本概念 2.安装与配置 3.生产与消费 4.服务端参数配置 二、生产者 1.客户端开发 必要的参数配置消息的发送序列化分区器生产者拦截器 2.原理分析 整体架构元数据的更新 3.重要的生产者参数 三、消费者 1.消费者与消费组 2.客户端开发 必要的…

【线程】屏障

一、主要函数应用 1. 函数原型&#xff1a;初始化和回收 int pthread_barrier_init(pthread *barrier, const pthread_barrier_t *attr, unsigned int count); int pthread_barrier_destroy(pthread_barrier_t *barrier);分析&#xff1a; 初始化屏障时&#xff0c;可以使用c…

中高级工程师Java开发!java生成随机数代码包

微服务是什么 微服务起源于2005年Peter Rodgers博士在云端运算博览会提出的微Web服务(Micro-Web-Service)&#xff0c;根本思想类似于Unix的管道设计理念。2014年&#xff0c;由Martin Fowler 与 James Lewis共同提出了微服务的概念&#xff0c;定义了微服务架构风格是一种通过…

Java软件开发面试题!hr和技术经理一起面

springspring5最全知识梳理大纲&#xff08;总&#xff09; spring最全知识梳理大纲&#xff08;总&#xff09; spring5最全知识梳理大纲&#xff08;总&#xff09; spring最全知识梳理大纲&#xff08;分&#xff09; 为什么要使用Spring&#xff1f; Bean spring事务 面向…