从进程表中删除僵尸进程


8

我有一个令人讨厌的僵尸进程,它被init采纳,并且不会消失。我读过一种方法,可以创建一个虚拟进程,将僵尸作为该新进程的子进程附加,然后将其杀死,然后将其从进程表中删除。

确切地说,我该怎么办?

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

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

要么

您应该重新启动系统

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

不幸的是,许多程序检查进程表以查看实例是否已在运行,并且如果进程表中有一项,则将拒绝启动新实例。

每当我的SSHFS连接断开时重新启动,并带上Sublime,都是很愚蠢的。


7
...用a弹枪 ;)
Nathan C

+1,因为我看着主体并看到了“杀死僵尸”
HopelessN00b 2014年

Answers:


16

摆脱僵尸的唯一方法是使其成为父系,wait()以便它可以报告其退出状态。您可以通过发送SIGCHLD给父母(假设父母编写正确)来做到这一点。

如果您有僵尸,这通常意味着父母的书写方式正确(因为孩子SIGCHLD在死亡而成为僵尸时已经发送给了父母),因此下一步就是杀死父母。
诸如pstree(带有该-p选项)之类的工具可以向您显示僵尸的血统,因此您知道哪个进程是父进程。
当父母去世时,僵尸将被收养init,这总是wait()让孩子死去,并乐于杀死所有收养的僵尸。

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

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


一些更有创意的人比我还拿出了这个选项,如果你想避免杀死父进程:

  1. 确定僵尸和父进程的PIDS
    (对于本例,假设僵尸是PID 3101,父进程是PID 3100)
  2. 火起来gdbattach父:
    attach 3100
  3. 呼吁waitpid僵尸:
    call waitpid(3101,0,0)
  4. 从上级(detach)分离并退出调试器。

(这是一种微调的狙击步枪。)


1
嘿,很好的答案。“莫辛”步枪就在那里。
Danila Ladner

1
@DanilaLadner我希望我能功不可没,但是直到我继续进行一点Google搜索以了解skerit对“将僵尸作为虚拟进程的子对象附加”的含义之后,我才想到使用调试器来强制执行waitpid()从未发生过的事情。我是一个糟糕的前程序员...
voretaq7

call waitpid永远不会为我回来
deFreitas

0

您为什么担心僵尸进程?他们占用的资源很少(用于骨架结构任务,PID的空间不多)。当然,这似乎还不算什么,但仅此而已。搜索他们的父母并修复它们,用更好的书面替代替代它们(可能会有其他有益的副作用),并报告为bug(他们当然是bug)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.