Linux系列: signal
2016-07-02
信号是进程间通信(ICP)的一种方式。简单而又强大。
信号的产生
信号是由内核管理的。 一般来说,信号的产生主要有三个原因:
- 程序运行出错
- 外部事件产生的信号
- 主动产生信号
错误,意味着程序将要做某个不可以做的事情,不能继续进行下去了。比如 除0操作,以及非法的地址访问;但是绝大多数错误是不会有信号产生的。比如,打开一个不存在的文件时,会发生错误,但是不会产生信号,只是open
会返回-1
而已。
外部事件产生的信号一般是指,I/O
有数据到达,或者是定时器到期,都会使用信号通知进程。还有就是子进程的终止也会向父进程发送信号(当子进程退出的时候,内核会向父进程发送SIGCHLD
信号)
主动产生信号意味着调用像kill
等函数主动产生一个信号。
信号的处理
- 执行缺省操作
- 忽略信号
- 自己编写
handler
函数处理
执行缺省操作,Linux
对每种信号都规定了默认操作。注意,进程对实时信号的缺省反应是进程终止。
忽略信号,即对信号不做任何处理,其中,有两个信号不能忽略:SIGKILL
及SIGSTOP
;
捕捉信号。定义信号处理函数,当信号发生时,执行相应的处理函数。
这时候可以想一下僵尸进程的产生过程:
当子进程完成自己的生命周期后,内核释放该进程所有的资源,包括打开的文件,占用的内存等。
但是会为其保留一些信息(包括进程号,退出码,退出状态,运行时间等),这些数据会一直保留到
系统将它传递给它的父进程为止,直到父进程通过调用wait / waitpid
来释放。
防止产生僵尸进程
如果父进程不关心子进程什么时候结束,那就可以用signal(SIGCLD, SIG_IGN)
或signal(SIGCHLD, SIG_IGN)
通知内核,自己对子进程的结束不感兴趣,那么子进程结束后,内核会回收,并不再给父进程发送信号。这样,
僵尸进程就会被回收。
当然也还有其他防止产生僵尸进程的做法,我们这里不再展开了。
多线程信号处理的问题:
这个暂时还没有遇到过,但是许多人都在讲多线程处理信号需要特别的注意,留坑,会专门找个时间学习一下。
###代码
使用Python
实现的signal
小例子