如何检查带有pid X的进程是否是一个僵尸?

我得到了一个进程的PID,我需要检查它是否是在C中使用POSIX系统调用的僵尸。我应该怎么做?

我遇到的问题是我有一个过程,它分叉给许多孩子,孩子们都做高管,有时我想在后台做exec,所以我不能等待()那些背景的孩子。 我可以定期等待(一次在我的主循环中),但我需要知道哪些进程是僵尸,所以我的父进程在等待不会很快结束的孩子时不会挂起。

如果你很好奇,我正在构建一个unix shell,并且它具有shell性质,让子进程异步执行。

您无法检查进程是否是具有纯POSIX调用的僵尸 – 除非您是父进程,并通过wait系列调用来获取它。 所以你必须找个好地方等孩子。

一种选择是设置SIGCHLD处理程序并在那里执行waitpid(0, &status, WNOHANG) 。 一定要循环,直到它不再找到任何进程 – 如果两个孩子在短时间内死亡,你可能只得到一个SIGCHLD

另一种选择是双叉 – 也就是fork() ,让孩子(称之为子A)再次使用fork,让第二个子(子B)执行。 然后孩子A立即退出。 同时,父母正在wait()孩子A的wait() 。一旦孩子A离开,系统的初始化过程将在孩子B最终死亡时负责收割。 这种方法比较简单,但是你的shell无法知道子B何时死掉,所以如果你需要这些信息,请使用前一种方法。

但是..但是……僵尸是一个孩子(在某种程度上)并且正在检查的过程是父母,对吗? 所以如果你担心一个特定的pid是一个僵尸,为什么不用WNOHANG做一个waitpid(2)并摆脱它呢? 现在,这将消耗退出状态,因此如果某个其他进程可能希望在将来真正wait ,则可能是个坏主意。

你提到你正在构建一个Unix shell; 你应该读一下: 正确处理SIGINT / SIGQUIT

通常,shell会在打印其提示之前不久检查已解散的子项 – 使用waitpid(2)系统调用和WNOHANG选项, WNOHANG 。 您可能还需要一个SIGCHLD处理程序 – 但如果您正忙着等待某个前台进程终止并且它实际上是一个终止的后台进程,那么您必须决定要对该信息做什么。

这只是当前所选答案的一个小变化。

那么shell命令’ps’如何显示活动进程表,你可以发现进程“已经不存在”? 我想必须有办法从c代码中获取该信息。