使用sigaction来取代signal作为信号处理器函数
早期ISO C提供了像这样的函数来支持自定义信号处理
typedef void (*sighandler)(int);
sighandler signal(sighandler func);
但是由于标准库并不涉及系统层次,所以很多细节方面都是未定义的,比如在执行某信号(下文均以SIGINT为例)的处理器函数时,是否阻塞该信号?
给出一段代码(均忽略了对系统调用的错误处理)
#include <stdio.h>
#include <signal.h> void handler(int sig)
{
if (sig == SIGINT)
{
sigset_t mask;
sigprocmask(SIGINT, NULL, &mask);
if (sigismember(&mask, SIGINT))
printf("执行SIGINT处理器函数时阻塞了该信号\n");
else
printf("执行SIGINT处理器函数时没有阻塞该信号\n");
}
} int main()
{
signal(SIGINT, handler);
raise(SIGINT);
return 0;
}
这段代码的执行结果是不确定的,参考APUE,早期版本signal函数的问题是在进程每次接到信号对其进行处理时会将该信号动作重置为默认值(即下面的处置方式1)。
回忆下,对信号的处置方式有3种:1、采取默认行为;2、忽略信号;3、调用处理器函数(记为handler)。
而这种行为是不可靠的,因为可能会导致信号的丢失。以考虑这样的时间顺序:
进入handler -> 又收到这个信号 -> 退出handler
虽然如果handler非常简单,其执行时间微乎其微的话,出现这种情况的可能性很小,但还是有出现的可能,这点不能置之不理。
结果就是,我们其实是想要用handler来取代默认行为,然后却执行了默认行为,假如默认行为是结束程序,那就是个问题了。
比如信号是SIGFPE(算术异常,比如0作为除数),我们要执行N次运算,每次都要检查,如果算术异常则将错误信息写到日志里(即handler的代码块),然后继续下次运算,我们不想因为一次运算错误而导致后面的运算都没进行就结束程序。
绝大多数情况下,可能handler内的代码执行时间很短,而SIGFPE短时间大量重复发送的可能性很小,导致一段有隐患的代码通过了测试。但是假如这段代码在长时间运行的服务器中,出现这种隐患的可能性越来越大,不可靠的signal函数很有可能会在某次出现问题。
虽然我们可以改变signal的内部实现,但由于不能跨平台,而且另一方面signal很多东西不能自定义,在最新的应用程序中应该使用sigaction来取代signal。
用法就是把上述代码的signal(SIGINT, handler);改成下面这样
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = 0; // 默认是执行处理器函数时阻塞该信号
// sa.sa_flags |= SA_NODEFER; // 若设置了SA_NODEFER, 则行为和早期的signal一样
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
通过像上述代码一样设置sa_flags来自定义处理器函数的行为,更多行为可以man 2 sigaction来查询手册
使用sigaction来取代signal作为信号处理器函数的更多相关文章
- 信号处理函数(3)-sigaction() 为信号注册信号捕捉函数
定义: int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact); 表头文件: #include& ...
- signal()函数说明
表头文件#include<signal.h> 功 能:设置某一信号的对应动作 函数原型:void (*signal(int signum,void(* handler)(int)))(in ...
- VxWorks 6.9 内核编程指导之读书笔记 -- Singnals
Signals 信号是操作系统用于异常处理和异步控制流的关键.在很多方面,信号相当于软件方面的硬件中的中断.操作系统产生的信号包括总线错误和浮点处理异常.信号也提供了API来管理和产生信号.在应用程序 ...
- Python语法速查: 13. 操作系统服务
返回目录 本篇索引 (1)sys模块 (2)os模块 (3)与Windows相关模块 (4)subprocess模块 (5)signal模块 (1)sys模块 sys模块用于Python解释器及其环境 ...
- signal函数、sigaction函数及信号集(sigemptyset,sigaddset)操作函数
信号是与一定的进程相联系的.也就是说,一个进程可以决定在进程中对哪些信号进行什 么样的处理.例如,一个进程可以忽略某些信号而只处理其他一些信号:另外,一个进程还可以选择如何处理信号.总之,这些总与特定 ...
- signal() 和 sigaction()
[摘自<Linux/Unix系统编程手册>] Unix系统提供了两种方式来改变信号处置:signal() 和 sigaction(). signal() 的行为在不同Unix实现间存在差异 ...
- UNIX环境编程学习笔记(25)——信号处理进阶学习之 sigaction 函数
lienhua342014-11-05 sigaction 函数跟 signal 函数一样,用于设置信号处理函数.此函数是用于取代 UNIX 早期版本使用的 signal 函数.UNIX 早期版本的 ...
- signal()函数
转自:http://blog.csdn.net/sddzycnqjn/article/details/7285760 1. 信号概念 信号是进程在运行过程中,由自身产生或由进程外部发过来的消息(事件) ...
- linux 信号signal和sigaction理解
今天看到unp时发现之前对signal到理解实在浅显,今天拿来单独学习讨论下. signal,此函数相对简单一些,给定一个信号,给出信号处理函数则可,当然,函数简单,其功能也相对简单许多,简单给出个函 ...
随机推荐
- grunt-init 默认模板目录更正
grunt-init是依赖grunt项目管理的脚手架工具,各种优点无须赘述,默认的template路径的作用:可以把自定义或其他模板放置其中,应用的时候直接调用模板名,不用每次寻找路径: 在安装gru ...
- VS2010制作安装程序
转自(http://blog.csdn.net/wenmang1977/article/details/7733685) 序 前些天想写一下制作安装程序,由于要写的内容比较多,一拖再拖,不过坚持就是胜 ...
- java程序设计基础篇 复习笔记 第五单元
1. method header: modifier, return value type, method signature(method name, parameter) method body ...
- 【javascript基础】 原生JSON.parse解析异常问题
[问题背景]用jQ,ajax返回json,返回的字符串如:{name:"suntiger035"},status:200,readyState:4,代码无任何问题,结果,succe ...
- 【前端工具】 在 Windows 下安装 GruntJS——教程(译)
在你安装 Grunt.js 之前你需要先安装 Node.js.对于本教程而言,我已经安装好了 node.js v0.10.0. 我将要安装 Grunt.js v0.4.1.警告:如果你已经安装了 Gr ...
- android mvp RxJava 框架结构分析
一个MVP结构:M是model,V是Fragment,P是提供者,P持有V和Model,控制获取数据并给V赋值.(结合了RXJava Retrofit和okHttp)
- JAVA怎么在函数内改变传入的值
public class TestInt { public int aa(int i) { return i+4; } public static void main(String [] args) ...
- OpenFlow技术白皮书-V1.0
1. 概述 OpenFlow是由斯坦福大学的Nick McKeown教授在2008年4月ACM Communications Review上发表的一篇论文OpenFlow: enabling inn ...
- 获取SQL Server数据库表的列名
SELECT syscolumns.name,systypes.name,syscolumns.isnullable,syscolumns.length FROM syscolumns, systyp ...
- stark组件
写一个stark组件仿造admin的功能 1:新建一个stark的app 问题:在django每次启动会扫描目录下所有的admin文件,需要扫描项目目录下的每个stark文件,我们需要怎么做 1:看在 ...