僵死进程及避免方法

1. 僵死进程

当一个程序创建的子进程比父进程提前结束,内核仍然保存一些它的信息以便父进程会需要它 - 比如,父进程可能需要检查子进程的退出状态。为了得到这些

信息,父进程调用‘wait()’;当这个调用发生,内核可以丢弃这些信息。

在子进程终止后到父进程调用‘wait()’前的时间里,子进程被称为‘僵死进程’ (‘zombie’)。(如果你用‘ps’,这个子进程会有一个‘Z’出现在它的

状态区里指出这点。)

也就是说,当子进程调用 do_exit() 后,子进程就终止了,与次进程相关联的所有资源都被释放掉了(假设进程是这些资源的唯一使用者)。 进程不可

运行,并处于TASK_ZOMBIE状态。它所占用的资源就是内核栈,thread_info结构和task_struct结构。此时进程存在的唯一目的就是向它的

父进程提供信息(子进程的退出代码,也就是exit()提供的,存储在task_struct中的exit_code成员)。父进程检索到信息后(通过wait()系统调用),


或者通知内核那是无关的信息后(在某些系统上,你可以指令系统你对子进程的退出状态没有兴趣,在SysV系统上,可以调用signal函数,

设置SIGCLD信号为 SIG_IGN,系统将不产生僵死进程, 详细说明参见<<高级编程>>10.7节),  由进程所持有的剩余内存被释放,归还给系统使用。

2. 怎样避免僵死进程的出现
需要却认父进程为每个子进程的终止调用‘wait()’(或者‘waitpid()’, ‘wait3()’,等等); 或者,在某些系统上,你可以指令系统你对子进程的退出状态没有兴趣。(译者注:在SysV系统上,可以调用signal函数,设置SIGCLD信号为 SIG_IGN,系统将不产生僵死进程, 详细说明参见<<高级编程>>10.7节)。


另一种方法是两次‘fork()’,而且使紧跟的子进程直接退出,这样造成孙子进程变成孤儿进程(orphaned),从而init进程将负责清除它。欲获得做这个的程序,参看范例章节的函数‘fork2()’。

为了忽略子进程状态,你需要做下面的步骤(查询你的系统手册页以知道这是否正常工作):

struct sigaction sa;
sa.sa_handler = SIG_IGN;
#ifdef SA_NOCLDWAIT
sa.sa_flags = SA_NOCLDWAIT;
#else
sa.sa_flags = 0;
#endif
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, NULL);

如果这是成功的,那么‘wait()’函数集将不再正常工作;如果它们中任何一个被调用,它们将等待直到*所有*子进程已经退出,然后返回失败,并且 ‘errno==ECHILD’。

另一个技巧是捕获SIGCHLD信号,然后使信号处理程序调用‘waitpid()’或 ‘wait3()’。参见范例章节的完整程序。

参考文献:

http://www.juntuan.net/hkbc/nixbc/unix/x178.htm

《APUE》

《LKD》

 

 

文章出处:http://www.diybl.com/course/6_system/linux/Linuxjs/200888/135107.html

你可能感兴趣的:(僵死进程及避免方法)