从进程表中删除僵尸进程

从进程表中删除僵尸进程

我有一个烦人的僵尸进程,它被 init 收养,而且它不会消失。我读到有一种方法可以创建一个虚拟进程,将僵尸进程附加为该新进程的子进程,然后然后杀死它,将其从进程表中删除。

我究竟该如何做呢?

是的,我已经阅读了大部分内容:

僵尸进程已经死亡,因此无法被杀死。

或者

你应该重新启动系统

僵尸进程不使用任何资源,你应该让它们

不幸的是,许多程序会检查进程表来查看实例是否已在运行,如果进程表中有条目,则会拒绝启动新实例。

每次我的 SSHFS 连接断开时,我都会重新启动,并带走 Sublime,这有点愚蠢。

答案1

仅有的摆脱僵尸进程的一种方法就是让它的父进程报告其退出状态。如果父进程写得正确,wait()您可以通过将其发送给父进程来实现这一点。SIGCHLD

如果你有僵尸,这通常意味着父母是不是写得正确(因为子进程SIGCHLD在死亡并成为僵尸进程时已经发送给了它的父进程),所以下一步是杀死父进程。类似(带有选项)
的工具可以显示僵尸进程的谱系,以便您知道哪个进程是父进程。 当父进程死亡时,僵尸进程将被收养,它总是等待子进程死亡,并会愉快地杀死它收养的所有僵尸进程。pstree-p
initwait()

如果父进程实际上已经是init(PID 1),那么您将处于一种不应该发生的情况。您可以尝试发送SIGCHLDinit,但您真的不应该这样做,如果这不起作用,您唯一的办法就是重新启动,因为您的系统init已损坏并且无法正常工作。

(这些是“散弹枪”选项。)


一些比我更有创造力的人如果您想避免终止父进程,也可以使用此选项:

  1. 确定僵尸进程和父进程的 PID
    (在这个例子中,假设僵尸进程的 PID 为 3101,父进程的 PID 为 3100)
  2. 启动gdbattach返回到父级:
    attach 3100
  3. 呼唤waitpid僵尸:
    call waitpid(3101,0,0)
  4. 与父级分离(detach)并退出调试器。

(这是一把经过精心调校的狙击步枪。)

答案2

为什么担心僵尸进程?它们占用的资源很少(用于骨架结构任务的空间、PID 和其他东西)。当然,这不太妥当,但就是这样。搜索它们的父进程并修复它们,用更好的替代方法替换它们(可能会有其他有益的副作用),将其报告为错误(它们肯定是)。

相关内容