linux后端服务程序之信号处理
信号就是通知某个进程发了某个事件,也称为软件中断。信号提供了一种处理异步事件的方法。信号通常是异步发生的,进程预先不知道信号准确发生的时刻。后端程序(daemon)往往需要提供7*24不间断的服务,因此,编程daemon程序时对信号的正确处理尤为重要。
下面和大家分享编写daemon程序时信号处理的注意事项,内容都来自Internet,只是进行了整理和总结。关于信号的基础只是请参考APUE。
常见的信号
SIGHUP 1 和终端的连接断开,发送该信号给控制进程。通常用此信号来通知daemon重新读取配置文件(因为daemon不会有控制终端,通常不会收到该信号)。
SIGINT 2 用户中断(Ctrl + C)。
SIGABRT 6 调用abort函数产生(通常是自杀)。
SIGKILL 9 可以杀死任意进程,不能被捕获或忽略(俗称酒杀)。
SIGSEGV 11 无效的内存引用(segmentation fault)。
SIGPIPE 13 对于socket fd,当一个进程向某个已经收到RST的fd执行写操作时,内核会向该进程发送该信号。
SIGTERM 15 kill命令发送的默认终止信号。
SIGCHLD 17 进程终止时向其父进程发送的信号。
SIGPROF 27 使用gprof工具测试时会收到该信号。
别用signal,用sigaction
可以通过signal或者sigaction函数来设置信号处理函数,但signal函数太过古老,因此推荐使用sigaction。理由如下:
1. sigaction可以提供更多接收到信号的信息。
2. 调用完信号处理函数后重新设置处理函数不会对sigaction有影响,因为sigaction默认是不会去重置处理函数的,同时在执行处理函数会屏蔽掉该信号,也不会有竞争。
3. signal函数在某些系统中会默认重启被中断的系统调用,而sigaction默认不会这样做。
4. signal函数在多线程环境中的行为是未定义的,必须使用sigaction函数。
数据传输和信号
使用了系统调用的函数都有可能被信号中断,立刻返回的函数(不需要等待I/O操作的完成或sleep)不会被中断,而需要等待的函数(等待网络传输,管道的读或者sleep)将会被中断,比如select, read, connect。
在daemon程序中,恰当地处理被中断的系统调用是非常重要的。如果read, write等传输数据的函数被中断,必须处理这种情况并恢复数据的传输。有两种被中断的场景:
1. 当没有数据传输时就被中断,函数返回-1,这时可以通过判断errno的值来识别这种错误,如果errno == EINTR,则表示函数在没有任何数据传输的情况下就被中断,这时可以通过同样的参数来再次调用该数据。
2. 另一种情况是数据传输已经在进行,但在没有完成之前被中断;这种情况下函数不会返回错误,而是返回一个小于期望大小的值,同时errno也不会有错误设置,想识别这种情况只能捕获导致中断的信号。在中断之后恢复数据传输时一定记得部分数据已经被传输,必须从正确的偏移再次发起传输。
不要通过sigaction函数设置SA_RESTART来处理被中断的系统调用。
多线程和信号
多线程程序的信号处理和单线程程序有很大的区别。根据POSIX规范,一个多线程的程序只有一个进程和一个pid,哪个线程会被中断并处理到达的信号呢?有两种情况:
不要在信号处理函数中使用锁。
同步化信号处理 signalfd
signalfd是一个在linux kernel 2.6.22提供的系统调用,功能是使用一个fd来接收信号。这样就可以同步地处理信号,也不需要设置处理函数。可以man signalfd 查看示例程序。首先必须使用sigprocmask来屏蔽要使用signalfd来处理的信号,然后调用signalfd创建一个fd用来读取到达的信号。当被屏蔽的信号到达时,程序将不会被中断,也不会有处理函数被调用。信号会在fd中排队。signalfd创建的fd可以和其他fd一样:可以放在select, poll, epoll中;可以设置为非阻塞;可以为不同的信号创建不同的fd;在fork之后该fd也不会关闭掉,子进程同样可以读懂发送给父进程的信号。signalfd非常适合在主循环中执行epoll处理大量连接的单进程网络服务程序中使用,信号的处理可以和其他fd一样加到epoll中。由于程序不会被中断,可以选择合适的时机才去处理信号。
建议继续学习:
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:千石 来源: 淘宝核心系统团队博客
- 标签: 信号
- 发布时间:2012-09-18 23:40:26
- [55] IOS安全–浅谈关于IOS加固的几种方法
- [53] android 开发入门
- [52] 如何拿下简短的域名
- [52] 图书馆的世界纪录
- [50] Oracle MTS模式下 进程地址与会话信
- [50] Go Reflect 性能
- [48] 【社会化设计】自我(self)部分――欢迎区
- [47] 读书笔记-壹百度:百度十年千倍的29条法则
- [36] 程序员技术练级攻略
- [27] 视觉调整-设计师 vs. 逻辑