使用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,此函数相对简单一些,给定一个信号,给出信号处理函数则可,当然,函数简单,其功能也相对简单许多,简单给出个函 ...
随机推荐
- jquery中prop和attr的区别
jquery中prop和attr的区别 prop: prop(name|properties|key,value|fn) **概述** 获取在匹配的元素集中的第一个元素的属性值. 随着一些内置属性的D ...
- Java 进阶7 并发优化 5 并发控制板方法
Java 进阶7 并发优化 5 并发控制板方法 20131114 前言: Java 中多线程并发程序中存在线程安全的问题,之前学习 Java的同步机制,掌握的同步方法只有一种就是使用 ...
- LeetCode OJ:Implement Stack using Queues(队列实现栈)
Implement the following operations of a stack using queues. push(x) -- Push element x onto stack. po ...
- 学习笔记之AutoLayout
Align:用来添加对齐约束. Pin:添加标准约束,比如相对于其他视图的大小和位置. Reslove Auto Layout Issues:可以让Xcode 自动生成约束,或者基于约束把子视图的边框 ...
- Spring核心概念(二)
IOC/DI IOC(控制反转):对象(组件)的创建由代码中转移到外部容器(XML,注解) . DI(依赖注入):当类A需要使用类B时,那么我们需要为类A的属性赋值类B的对象. 这种现象我们称为依赖注 ...
- index、noindex、follow、nofollow的使用说明
爬虫是目前最常见的网络程序,曾经有过统计,说是目前的网络流量有一半以上是爬虫使用的.虽然爬虫程序随处可见,但是并不代表这种做法就是合理合法的. 在抓取网页时,我们要让自己的爬虫遵守Robot.txt协 ...
- EasyPusher RTSP推流/EasyRTMP RTMP推流Android安卓摄像头视频偏暗的问题解决方案
本文转自EasyDarwin团队成员JOHN的博客:http://blog.csdn.net/jyt0551/article/details/75730226 在我们测试EasyPusher/Easy ...
- JMter中添加断点和关联
一. 断点 断言是什么呢,它是用来检查返回结果对不对的. 用来验证结果是否正确,如果正确的话,就代表这个请求的返回是正确的,如果没有的话就代表这个请求的结果和我们预期的不一致,这 ...
- mailto web弹出outlook发送邮件
1. <pre name="code" class="html"><a href="Mailto:test@163.com?CC=t ...
- iOS runloop 自定义输入源
创建自定义输入源需要定义以下内容 1)输入源要处理的信息 2)使感兴趣的客户端知道如何和输入源交互的调度例程 3)处理其他任何客户发送请求的例程 4)使输入源失效的取消例程 上图的处理流程:主线程(M ...