全部博文(85)
分类: LINUX
2010-01-15 10:34:34
9.3 僵死进程
僵死进程是已经终止,但没有从进程表中清除的进程。代码9-12展示了一个产生僵死进程的例子:
代码9-12 僵死进程产生模型(节自/code/chapter9/szomb1.c)
#include |
编译代码9-12:
# make szomb1 |
后台运行程序szobm1,并在子进程结束后,父进程没有结束前,运行命令查询进程情况:
# ./szomb1& |
其中"
当子进程终止时,它释放资源,并且发送SIGCHLD信号通知父进程。父进程接收SIGCHLD信号,调用wait返回子进程的状态,并且释放系统 进程表资源。故如果子进程先于父进程终止,而父进程没有调用wait接收子进程信息,则子进程将转化为僵死进程,直到其父进程结束。
一旦知道了僵死进程的成因,我们就可以采用如下方法预防僵死进程:
1. wait法
父进程主动调用(或者接收到SIGC(H)LD信号后调用)wait接收子进程的死亡报告,释放子进程占用的系统进程表资源。如将代码9-10中屏蔽的代码行①"wait();"打开,就可以有效的阻止僵死进程的产生。
2. 托管法
如果父进程先于子进程而死亡,则它的所有子进程转由进程init领养,即它所有子进程的父进程ID号变为1(进程init的标识为1)。当子进程结束时init为其释放进程表资源。
3. 忽略SIGC(H)LD信号
当父进程忽略SIGC(H)LD信号后,即使不执行wait,子进程结束时也不会产生僵死进程(有关信号的相关知识将在下一章讲述)。
3. 捕获SIGC(H)LD信号
当父进程捕获SIGC(H)LD信号,并在捕获函数代码中等待(wait)子进程。
【实践经验】实现托管法的技巧是调用fork两次,让子进程退出,子子进程的父进程更改为进程init,这样父进程就不必理会子子进程的处理了。代码9-13设计了一个两次fork避免僵死进程的例子。
代码9-13 托管法预防僵死进程(节自/code/chapter9/szomb2.c)
#include |
编译代码9-13:
# make szomb2 |
后台运行程序szobm2,并在子进程结束前,运行命令查询进程情况:
# ./szomb2& |
上例中,进程10733的父进程标识号已经更改为1,即已经由系统进程init(标识号为1)托管。