在Linux系统上如果一个进程死亡,这个进程就会变成僵尸进程,需要该进程的父进程去给其收尸,这个过程有一个很形象的称呼,叫做”reaping the zombies”。

之前有个疑问,为什么要做僵尸进程这样的设计?思来想去,这应该是父子进程通信的一种方式吧,子进程死亡后留下僵尸进程,留给父进程一个机会去获取子进程的状态。

下面是做实验时间,写一个简单的Python2.7脚本来产生僵尸进程:

执行上面的脚本,会产生一个僵尸进程。因为父进程处于signal.pause()状态时子进程退出了,父进程没有来得及给子进程收尸。一次执行的输出是:

我们用ps u命令来查看进程列表,可以看到:

PID为457的子进程成为僵尸进程,被标志为Z+

避免僵尸进程

既然僵尸进程的存在是为了让父进程有机会捕获子进程的退出状态,那么在机制上它应该是可以避免的。

Stack Overflow上的这篇文章Why zombie processes exist?{.question-hyperlink}给出了几种方法,其中一种是直接告诉系统,你不想关心子进程状态,压根不要产生僵尸进程。方法是忽略父进程的SIGCHLD信号,这样子进程退出后就不会存留僵尸进程。

修改一下前面的Python脚本,忽略SIGCHLD信号:

运行输出:

ps u查看进程状态,发现原先的僵尸进程已经不存在了:

清理僵尸进程

综上所述,僵尸进程的存在是因为子进程退出了,而父进程没有收尸。这其实是程序设计上的失败。如果产生这种情况,只能通过杀死那些父进程,让init进程接管所有的僵尸进程为其收尸了。

How to kill zombie process{.question-hyperlink}给了一个非常好的命令行:

完。