今天碰到一个老问题,就是防止僵尸进程的出现,于是又在网上学习了一遍,写到这里,防止以后不再有一个地方重新学习,:)
一、什么是僵尸进程
这个首先要了解一下linux下的进程在结束的时候会做什么事情。linux下的进程在结束后,会向它的父进程发送一个SIGCHLD的信号,但是它仍然会在系统内存中保留一些数据,比如它占用的PID,以及它自己的结束状态(我猜测留下来的就是task_struct结构体,不过没有进行代码验证);保留这些信息的作用就是期待它的父进程调用wait()系统调用时,可以返回自己的结束状态;在父进程调用完wait()之后,该进程就真正地从内存中消失的无影无踪。
那么,僵尸进程就是指,已经结束,但是还没有被它的父进程调用wait/waitpid的进程。
二、产生僵尸进程的原因
如果父进程出于一些原因没有调用wait(),或者是因为程序bug,或者是父进程真的就不想长时间的等待子进程结束(一些进程池的实现,而且wait是blocking的调用),那么僵尸进程就会出现。
三、僵尸进程的影响
因为僵尸进程在内存中所保存的状态很少,所以如果不是大量的僵尸进程存在是不会影响系统性能的。不过,如果你的系统中僵尸进程的数目持续增长的话,那么的确不是什么好兆头。因为僵尸进程会保留PID,而PID这个资源对于linux来说又是非常宝贵的,如果僵尸进程的数目快速增长的话,它会快速消耗掉系统内可用的PID,那么你的系统就有可能不能再启动新的进程了。这意味着什么?那就是有可能你连ls
命令都不能执行,因为ls
也是个进程呀!
四、如何消灭掉系统内的僵尸进程
由于这些进程已经是僵尸进程了,是DEAD的了,你是不能通过kill
命令清除掉这些僵尸进程的。那么唯一可以利用的就是系统的init
进程,没错,就是那个PID为1的进程。
一般可以认为init
进程没有什么bug,针对托管给它的僵尸进程,它可以正确调用wait()、waitpid()来终止掉这些进程。那么如何才能将这些僵尸进程托管给init
进程呢?我想到的办法就是kill
掉它们的父进程。如