如果没有清除僵尸状态有什么问题吗?

Rav*_*avi 19 linux process

我有一个生产单元,其中 Java 进程已成为僵尸,并且现在在那里停留了一段时间。如果设备重新启动,则它将被清除。但是,该单元并未重新启动,并且另一个 java 进程已启动并正在运行。如果这个僵尸状态没有清除它就保持原样,会有什么问题吗?它会以任何方式(性能或缓慢)产生影响吗?

小智 23

僵尸进程不会对性能或缓慢产生任何影响,因为僵尸进程不会占用任何系统资源。

注意:- 实际上,它仍在使用 PID(这是一种有限的资源),并且仍在分配进程的内核数据结构。通常,这无关紧要,但在内存非常有限的系统上,内核内存使用量可能很大。

僵尸进程引起的问题

每个僵尸进程都保留其进程 ID。Linux系统有进程ID的数量有限- 32767默认情况下在32位systems.If僵尸以非常快的速度正在积累,现有的PID整池最终将成为分配给僵尸进程,防止其他进程启动。

注意:在 64 位系统上,您可以增加最大 PID,参见https://unix.stackexchange.com/a/16884/170373

然而,一些僵尸进程没有问题——尽管它们确实表明您系统上的父进程存在错误。

解释:

当一个进程在 Linux 上死亡时,它不会立即从内存中全部删除——它的进程描述符保留在内存中。

进程的状态变为EXIT_ZOMBIE,进程的父进程被通知它的子进程已经随着SIGCHLD信号死亡。

然后父进程应该执行 wait() 系统调用来读取死进程的退出状态和其他信息。这允许父进程从死进程中获取信息。调用wait()后,僵尸进程从内存中彻底清除。

这通常发生得非常快,因此您不会看到僵尸进程在您的系统上堆积。然而,如果父进程没有正确编程并且从不调用wait(),它的僵尸子进程将留在内存中,直到它们被清理干净。

解析度:

你不能杀死僵尸进程,因为你可以用 SIGKILL 信号杀死正常进程——僵尸进程已经死了。

杀死僵尸的一种方法是向父进程发送 SIGCHLD 信号。这个信号告诉父进程执行wait()系统调用并清理它的僵尸子进程。使用 kill 命令发送信号,将下面命令中的 pid 替换为父进程的 PID:

kill -s SIGCHLD pid
Run Code Online (Sandbox Code Playgroud)

当创建僵尸进程结束时,init 继承僵尸进程并成为它们的新父进程。(init 是启动时在 Linux 上启动的第一个进程,并被分配了 PID 1。)

注意:-从 Linux 3.4 开始,进程可以发出带有 PR_SET_CHILD_SUBREAPER 选项的 prctl() 系统调用,因此它们,而不是进程 #1,将成为其孤立后代进程的父进程。参考:https : //unix.stackexchange.com/a/177361/5132  

然后 INIT 执行 wait() 系统调用来清理它的僵尸子进程,因此 init 将缩短僵尸的工作时间。您可以在关闭父进程后重新启动它。

  • 在 64 位系统上,可以增加最大 PID,参见 https://unix.stackexchange.com/a/16884/170373 (3认同)
  • 当现在是僵尸进程死亡时,父进程将已经收到一个 SIGCHLD。 (2认同)
  • 严格来说,说它不使用资源是不正确的。它仍在使用 PID(这是一种有限的资源),并且仍在为进程分配内核数据结构。通常,这无关紧要,但在内存非常有限的系统上,内核内存使用量可能很大。 (2认同)

小智 6

大多数情况下,僵尸不是一个大问题。它们是一个“死”的进程,它不需要 CPU 时间,并且任何分配的内存都应该在死亡之前被进程释放。他们实际占用的唯一资源是您的进程列表中的一个条目。根据您的系统,您可以拥有允许的最大线程数,并且僵尸可以让您无缘无故地更快地达到此限制。

但是:僵尸通常是由于代码错误/错误而出现,程序员忘记检查其子进程的状态。这可能是故意的,但通常不是。错误/错误代码通常也会以一种糟糕的 特殊方式处理内存,并且释放一些分配的资源。如果是这种情况,这些资源将继续分配给僵尸,直到它完全终止。

编辑:如果进程是一个 java 程序,未释放的内存应该不是问题,因为 java 垃圾收集器会处理一切。

  • 事实上,大多数操作系统在所有语言中都不会发布非馈送内存。系统将释放除父进程的少量内存之外的所有内存。 (3认同)