孤儿进程与僵尸进程
Posted 扫驴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了孤儿进程与僵尸进程相关的知识,希望对你有一定的参考价值。
以下部分引用自https://www.cnblogs.com/Anker/p/3271773.html
首先说明,每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。 但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等)。直到父进程通过wait / waitpid来取时才释放(给子进程送终)。释放完了这个子进程就彻底消失了,用ps命令也查不到了。
而在子进程退出,内核释放了子进程所有的资源以后,父进程没有通过wait/waitid来获取并释放之前,这个进程的状态就是僵尸状态(Z状态),所以说,僵尸状态是每个进程都会经历的过程。
为了说明问题,先要了解,subprocess包是python创建子进程的包,其中有两个方法,一个是call,一个是Popen,二者的区别是,调用call方法的父进程,会等待子进程执行完毕并给其送终(父进程调用wait来获取退出信息(主要是状态码)并释放子进程id),然后才接着执行,而popen则不同,父进程创建了子进程后,就接着执行自己的代码了。所以,调用call我们捕捉不到子进程变为僵尸进程的短暂瞬间,而popen却有办法捕捉到,以下是代码:
1 import time 2 import subprocess 3 child = subprocess.Popen(["ping","-c","10","www.baidu.com"])#子进程创建完毕,父进程接着执行print 4 print "fffffffffffffffffffffffffffffff" 5 time.sleep(40)#父进程活了40秒,而子进程10秒就死了,在子进程死亡以后父进程未死亡之前,父进程并没有给子进程送终,而是干自己的事情。这个阶段子进程就是僵尸状态。
如果把以上代码popen换成call,则就捕捉不到子进程变为僵尸状态的瞬间了,因为父进程等待子进程死亡并给其送终后,才执行print。
假如,以上代码,父进程长生不老,并且一直在制造子进程,并且主要是制造了子进程以后还不为他送终(),那么随着子进程一个个的成为僵尸进程,保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 这是有害的,所以要避免这种情况的发生。
而事实上上述代码,父进程存活了40多秒,父进程死亡后,被其自己的父进程送终,而其子进程(注意此时其子进程属僵尸态)则由init进程接管,init进程马上给他送终
那什么是孤儿进程呢?把以上代码,time.sleep(40)去掉,也就是说让父进程早于子进程死亡,那么此时的子进程就是孤儿进程了,但是他随即就会被过季给init进程(此时用ps命令可查看到这个子进程的ppid已经变为1了),由init来尽其生父未尽之事,因此孤儿进程并不会有什么危害
纠正一点,子进程的退出码是返回给系统的,并不是返回给父进程的,父进程通过wait调用,才能得到此退出码
说一下通过popen创建的子进程,父进程如何为其送终
import time import subprocess child = subprocess.Popen(["ping","-c","10","www.baidu.com"])#子进程创建完毕,父进程接着执行print print "fffffffffffffffffffffffffffffff" time.sleep(40) child.wait()#这就是送终
简而言之,父进程以死,子进程还在运行,这个子进程就是孤儿进程。父进城还活着,子进程已经结束运行,父进城没有给紫禁城收尸就是僵尸进城
kill -9 pid是杀不死僵尸进城的,他能将进城的状态从正在运行态变成僵尸态,却不能将僵尸态变为消亡。要想杀死僵尸态,只能kill -9 ppid(此ppid指的是僵尸进城的附近成)
以上是关于孤儿进程与僵尸进程的主要内容,如果未能解决你的问题,请参考以下文章