APUE学习笔记:Linux下signal和sigaction的使用区别
来源:互联网 发布:泼墨软件 编辑:程序博客网 时间:2024/05/23 01:12
《UNIX环境高级编程》第三版,图10-20在Linux环境下的运行结果与书中所述有所不同,信号处理函数执行期间未自动屏蔽该信号,详见:
信号之sigsetjmp和siglongjmp函数
其原因在于:
- glibc 2之后,如果系统定义了_BSD_SOURCE宏或_GNU_SOURCE宏的话,那么系统将通过调用sigaction函数的方式去实现signal函数,否则signal函数将遵循System V语义
signal函数在System V下的语义:
- 信号处理函数被调用后,该信号的处理方式被重置为默认处理方式,因此在信号处理函数中要用signal函数对信号重新注册
- 信号处理函数执行期间,该信号未被自动屏蔽
因此书中例程可修改为
#include "apue.h"#include <setjmp.h>#include <time.h>#include <errno.h>static void sig_usr1(int);static void sig_alrm(int);static sigjmp_buf jmpbuf;static volatile sig_atomic_t canjump;int main(void){#ifdef _BSD_SOURCE if(signal(SIGUSR1, sig_usr1) == SIG_ERR) err_sys("signal(SIGUSR1) error"); if(signal(SIGALRM, sig_alrm) == SIG_ERR) err_sys("signal(SIGALRM) error");#else struct sigaction sa_usr1, osa_usr1, sa_alrm, osa_alrm; struct sigaction *sa_usr1_p, *osa_usr1_p, *sa_alrm_p, *osa_alrm_p; sa_usr1_p = &sa_usr1; osa_usr1_p = &osa_usr1; sa_alrm_p = &sa_alrm; osa_alrm_p = &osa_alrm; sa_usr1_p->sa_handler = sig_usr1; sigemptyset(& sa_usr1_p->sa_mask); sa_usr1_p->sa_flags = 0; sa_alrm_p->sa_handler = sig_alrm; sigemptyset(& sa_alrm_p->sa_mask); sa_alrm_p->sa_flags = 0; if(sigaction(SIGUSR1, sa_usr1_p, osa_usr1_p) == -1) err_sys("sigaction(SIGUSR1,,) error"); if(sigaction(SIGALRM, sa_alrm_p, osa_alrm_p) == -1) err_sys("sigaction(SIGALRM,,) error");#endif pr_mask("starting main: "); if(sigsetjmp(jmpbuf, 1)) { pr_mask("ending main: "); exit(0); } canjump = 1; for(;;) pause();}static void sig_usr1(int signo){ time_t starttime; if(canjump == 0) return; pr_mask("starting sig_usr1: "); alarm(3); starttime = time(NULL); for(;;) if(time(NULL) > starttime + 5) break; pr_mask("finishing sig_usrr1: "); canjump = 0; siglongjmp(jmpbuf, 1);}static void sig_alrm(int signo){ pr_mask("in sig_alrm: ");}
或者可以使用以下两种方法:
关于__GNU_SOURCE 这个宏
gcc中一个编译选项 -D_GNU_SOURCE
程序运行结果:
以下引自《Linux程序员手册》:
- 只有在信号的处理方式被设为SIG_DFL和SIG_IGN的情况下,signal函数才是可移植的,其他情况下,signal的语义取决于系统的具体实现。
- 在早先的UNIX系统中,使用signal函数安装信号处理函数,等同于以sa.sa_flags = SA_RESETHAND | SA_NODEFER的方式调用sigaction函数,同时在信号处理函数执行期间,该信号的传递未被自动屏蔽
- BSD对此做了优化,等同于以sa.sa_flags = SA_RESTART的方式调用sigaction函数,同时引入了信号的自动屏蔽机制
- Linux则遵循以下语义:
(1)若signal为内核的系统调用函数,则遵循System V语义
(2)glic2及以后,signal函数不再执行内核系统调用,如果_BSD_SOURECE功能测试宏已定义,那么遵循BSD语义,若_GNU_SOURCE被定义,则_BSD_SOURECE被隐式定义 - 推荐使用sigaction而非signal函数注册信号!
阅读全文
0 0
- APUE学习笔记:Linux下signal和sigaction的使用区别
- APUE学习笔记——10信号——信号接口函数 signal 和 sigaction
- linux signal, sigaction.sa_mask, sigwait的区别
- 信号处理:signal和sigaction的区别
- 源码剖析signal和sigaction的区别
- 记signal和sigaction的一个区别
- linux的信号学习 ,signal(),sigaction()
- linux c ---signal 和sigaction
- linux c 之signal 和sigaction区别 (转载)
- APUE--sigaction函数的使用
- linux 0.11版本内核中信号signal()和sigaction()的区别
- linux 下 signal 与sigaction 对信号的处理差异
- Linux信号,signal和sigaction(一)
- linux 信号signal和sigaction理解
- linux 信号signal和sigaction理解
- linux 信号signal和sigaction理解
- linux 信号signal和sigaction理解
- linux 信号signal和sigaction理解
- 对单表亿级数据的简单测试
- ASP.NET MVC 此安装不支持该项目类型解决方法
- 用cmd命令生成项目webservice客户端
- Snackbar和Toast的花式使用,这一篇就够了
- Tempest之Testr使用
- APUE学习笔记:Linux下signal和sigaction的使用区别
- 产品经理如何高效与设计师沟通?
- Django学习笔记1 [路由机制,数据库orm,模板语言]
- 前端学习笔记3:CSS简介及CSS选择器
- (Linux)CentOS7.3中的jdk和tomcat配置
- 自顶向下深入分析Netty(二)--线程模型
- MySQL优化之如何了解SQL的执行频率
- Hibernate获取数据java.lang.StackOverflowError
- Educational Codeforces Round 23 B