僵尸进程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了僵尸进程相关的知识,希望对你有一定的参考价值。

fork()以后,父进程和子进程是并发执行的,父进程永远无法预测子进程什么时候结束。当子进程完成它的工作退出后,其父进程需要调用wait()或者waitpid()获取子进程的退出状态。

孤儿进程:
1) 父进程退出后,若它的子进程还在运行,那么这些子进程将成为孤儿进程。
2) 孤儿进程将被init进程(pid为1)所收养,并由init进程对它们完成状态信息释放工作。
3) 孤儿进程对系统没有危害。

僵尸进程:
1) 父进程使用fork创建子进程后,如果子进程退出后,父进程并没有调用wait或waitpid来释放子进程的状态信息,那么子进程的进程描述符仍然残存在系统中,这种进程便称为僵尸进程。
2) ps时仍然能看到子进程,其进程状态为Z。
3) 通俗点说,就是进程已经退出了,其进程资源也回收了,但其pid和状态信息仍然占据在内核中的进程就是僵尸进程。
4) 僵尸进程的危害在于大量僵尸进程会导致系统pid耗尽。
5) 需要注意的是,进程调用exit正常退出后,立即ps时可能会短暂看到其状态为Z,稍后才会消失。因此不能通过立即getpid来判断它是否退出了。

为什么必须调用waitpid才能不成为僵尸进程?
Unix提供了一种机制用于父进程获取子进程结束时的状态信息,方法是: 在进程退出时,内核只释放该进程所持有的资源,如打开的文件句柄、申请的内存等,但仍为其保留一些状态信息(包括进程pid、退出状态、运行时间等,直到父进程通过wait或waitpid来获取时才释放。但这样就导致了问题,如果父进程永远不调用wait或waitpid的话,那么保留的这些状态信息就不会被释放,其进程pid也就会一直被占用,这样就形成了僵尸进程。

僵尸状态:
任何一个进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是Z。如果父进程能及时处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。如果父进程在子进程结束之前退出,则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理。

详细参考:
http://www.cnblogs.com/Anker/p/3271773.html

 

---- 若只wait 1秒,但父进程也是常驻,子进程过3秒后才退出,是否仍然成为僵尸?

waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。

进程pid:

递增的关系,不会立即占用,直到没有可利用时才会从头找已释放的pid使用。
因此,两次ps查看发现pid相同,说明进程并未退出,而绝不会是退出后又被立即拉起。

以上是关于僵尸进程的主要内容,如果未能解决你的问题,请参考以下文章

如何察看僵尸进程 zombie

忽略SIGCHLD信号能避免僵尸进程吗

linux僵尸进程产生的原因以及如何避免产生僵尸进程

孤儿进程和僵尸进程

PHP僵尸进程

PHP僵尸进程