使用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,此函数相对简单一些,给定一个信号,给出信号处理函数则可,当然,函数简单,其功能也相对简单许多,简单给出个函 ...
随机推荐
- Web字体(链接)嵌入
下面是我最近在学习的两种字体嵌入方法 1.@font-face 使用@font-face可以这样做: @font-face{ font-family:"Garamod Premier Pro ...
- 转:Hive SQL的编译过程
Hive是基于Hadoop的一个数据仓库系统,在各大公司都有广泛的应用.美团数据仓库也是基于Hive搭建,每天执行近万次的Hive ETL计算流程,负责每天数百GB的数据存储和分析.Hive的稳定性和 ...
- Java 进阶6 异常处理的陷阱
Java 进阶6 异常处理的陷阱 20131113 异常处理机制是 Java语言的特色之一,尤其是 Java的Checked 异常,更是体现了 Java语言的严谨性:没有完善的错误的代码根本就不会被执 ...
- WTH统计
SELECT t2.MasterName AS '类型',SUM(t1.DailyCount) AS '数量',(CASE T2.MasterName WHEN '电子阅读' THEN '篇' WHE ...
- 在Linux下设置定时任务(每分钟执行一次特定的shell脚本)
在当前用户下,开始编辑定时任务 crontab -e 按键 i 进入编辑模式 输入下述命令 */ * * * * sh /***/*****.sh 然后按键 Esc 退出编辑模式,再输入 wq 保存退 ...
- Django中类视图使用装饰器的方式
类视图使用装饰器 为类视图添加装饰器,可以使用两种方法. 为了理解方便,我们先来定义一个为函数视图准备的装饰器(在设计装饰器时基本都以函数视图作为考虑的被装饰对象),及一个要被装饰的类视图. def ...
- diff和patch 打补丁
在Linux环境下,有两个工具用来给project打补丁,即diff和patch diff diff具有比较功能.可以使用man命令查看其使用方法. NAME diff ...
- L163
Chickens slaughtered in the United States, claim officials in Brussels, are not fit to grace Europea ...
- 2017.10.24 A test error about ATE device
1 A misunderstands on E-mail Customer: The initial red blink just means theXXX unit has not yet s ...
- widow系统 LuaForWindows,安装 luasocket
参考 http://94it.net/a/jingxuanboke/2013/0625/49052.html 1. 我用的是 LuaForWindows_v5.1.4-46.exe 可以在我的百度网盘 ...