使用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,此函数相对简单一些,给定一个信号,给出信号处理函数则可,当然,函数简单,其功能也相对简单许多,简单给出个函 ...
随机推荐
- 转:聊聊Greenplum的那些事
笔者有幸从04年就开始从事大规模数据计算的相关工作,08年作为Greenplum 早期员工加入Greenplum团队(当时的工牌是“005”,哈哈),记得当时看了一眼Greenplum的架构(嗯,就是 ...
- LeetCode OJ:Isomorphic Strings(同构字符串)
Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic if the chara ...
- 正则表达式 preg_match 匹配中文
preg_match 匹配中文出错 2010年01月06日 星期三 14:55 错误提示: Warning: preg_match() [function.preg-match]: Compilati ...
- java语言基础-变量
一丶变量的基本概念 1.什么是变量 (1).内存中的一个存储区域 (2).该区域有自己的名称(变量名),和类型(数据类型) (3.)该区域的数据可以在同一类型范围内不断变化(定义变量的主要目的是因为数 ...
- 编译安装pgbouncer-checking for OpenSSL... configure: error: not found
花了一上午时间将pgbouncer的参数通读了一遍,对他有个大致的了解:1.配置分为连接池和pgbouncer两个部分[database]\[pgbouncer ].2.一条记录对应创建一个连接池,连 ...
- jsp笔记总结
第一章 JavaWeb简介 1.什么是Web应用程序 什么是Web应用程序是一种通过Web访问的应用程序.Web应用程序一个最大优点就是用户很容易访问.用户只需要有浏览器即可,不需要再安装其他软件.W ...
- [AirFlow]AirFlow使用指南一 安装与启动
1. 安装 通过pip安装: xiaosi@yoona:~$ pip install airflow 如果速度比较慢,可以使用下面提供的源进行安装: xiaosi@yoona:~$ pip insta ...
- Java集合体系总结
一.集合框架 集合是容纳数据的容器,java常用的集合体系图如下.以集合中是否运行重复元素来分,主要有List和Set接口,List集合中可以有重复元素,Set集合集合中的元素不可重复,Iterato ...
- Vim技能修炼教程(9) - 缓冲区和标签页
缓冲区 上一节我们学习了窗口相关的命令,其实多窗口的最大功能在于存放多个不同的缓冲区. 文件载入内存之后,我们操作的其实是缓冲区.:write命令就是将缓冲区写回文件的目的. 查看内存中的缓冲区 通过 ...
- Android Kill Process
/********************************************************************** * Android Kill Process * 说明: ...