UNIX僵尸进程和守护进程

8
我理解当一个进程没有很好地清理(其资源未被回收/收割)时,就会创建一个僵尸进程。在调用fork()创建新进程后,父进程应始终调用waitpid来清理它。
我还了解到,通过复制一个由fork创建的子进程并让该子进程死亡,可以创建守护进程。显然,在这样做后,UNIX中的init进程(pid#1)将接管该进程。
我想知道的是-据我所知,当父进程死亡时,它会自动清理子进程-那么,为什么会首先创建一个僵尸进程?
其次,守护进程的父进程死亡,那么为什么守护进程不被视为僵尸进程?

2
有人想针对匿名的踩和关闭请求发表评论吗?我觉得这是一个相当不错的问题。 - John Humphreys
2
可以说这更像一个服务器故障问题,但进程管理对*nix编程也很相关,所以我认为这个问题不是很大。 - Neil Aitken
1
进程的父进程已经死亡的被称为孤儿进程,而不是僵尸进程。僵尸进程是“活死人”;孤儿进程可以成为有生产力的社会成员。 - Jonathan Leffler
这个问题有两个错误的假设。第一个是关于僵尸进程性质的,@blagovest-buyukliev的回答已经解决了这个问题。另一个是关于守护进程性质的,这个问题没有被解决,所以我来解释一下:守护进程是UNIX/Linux中服务的等价物。它们只是在后台运行的进程。通常由init系统(如SysV init或systemd)进行管理(启动/停止/监视等)。 - ivant
2个回答

15
我想知道的是-据我所知,当一个父进程终止时,它会自动清理子进程-那么僵尸进程是如何被创建的呢?
不,父进程并不会自动清理所有子进程。每当一个进程终止时,无论它正在运行还是处于僵尸状态,都会被init进程接管。
僵尸进程是已经终止的子进程,在其父进程仍然存活但尚未调用wait获取其退出状态时存在。如果父进程死亡(且未调用wait),则由init进程接管所有的僵尸子进程,并最终调用wait对其进行回收,从而使它们消失在进程表中。
保持僵尸进程的想法是为了保留有关进程终止的适当数据结构,以防父进程通过wait变得感兴趣。
另外,守护进程的父进程结束后,为什么守护进程不被视为僵尸进程?
守护进程的父进程会结束,但守护进程通过setsid系统调用分离出控制终端并成为进程组长。

挑剔的问题:除进程1之外,所有进程都是子进程,僵尸进程只是其中一种“活死人”,即已经死亡但其父进程尚未等待收集尸体状态的进程。僵尸进程是一个问题,因为它占据了进程表中的一个插槽,直到尸体被清理掉后才能被重用(由原来的父进程或系统进行清理,如果父进程在等待期间死亡,则由系统进行清理)。在极端情况下(200,000个僵尸进程),它们会严重拖慢系统速度。我今年早些时候遇到了这个问题:每分钟从系统进程产生三个僵尸进程。操作系统更新! - Jonathan Leffler
2
这个不错的答案还有一个补充:保留僵尸进程的原因之一是在父进程处理终止消息之前,PID 不应该被重用。 - Drunix

0

当一个子进程启动时,内核级别会创建一个条目以及其父进程ID。由于某种原因(服务器故障,应用程序端杀死父进程等),父进程被杀死而子进程仍在运行。内核无法清理这样的进程。只有父进程有权这样做。因为这样的进程仍然在内核表中,所以它也在消耗资源,但却没有任何作用。因此,它被称为僵尸进程。


1
在早期版本的Solaris中,只有父进程被授权清理子进程,但从Solaris 11开始,如果父进程死亡,init进程将自行清理所有僵尸进程。 - sumana

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接