您可以拥有的僵尸进程数量上限吗?


17

我曾经使用过HP-UX系统,老管理员告诉我,系统上的僵尸进程数量有上限,我相信是1024。

  • 这是一个困难的事实上限吗?我认为您可以拥有任意数量的僵尸,就像可以拥有任意数量的进程一样……?
  • 发行版与发行版之间是否有不同的价值?
  • 如果我们达到上限并尝试创建另一个僵尸会发生什么?

1
根据这篇博客文章,Linux上的唯一限制是PID的数量,PID只能偶然影响僵尸。
bahamat 2012年

2
下面的两个答案都提到了ulimit -u。有一段时间我很困惑,因为man ulimit我没有提到C例程-u。提到的ulimit实际上是内置的bash工具,在bash联机帮助页中对此进行了描述。
伊曼纽尔·伯格

Answers:


11

我没有可用的HP-UX,而且我从来都不是HP-UX的忠实拥护者。

看来在Linux上,存在多少子进程的每个进程或每个用户的限制。您可以使用limit内置的Zsh 看到它(似乎类似于ulimit -ubash中的代码):

1002 % limit
cputime         unlimited
filesize        unlimited
datasize        unlimited
stacksize       8MB
coredumpsize    0kB
memoryuse       unlimited
maxproc         16136
  ...

那是在一台Arch Linux笔记本电脑上。

我编写了一个小程序来测试该限制:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

volatile int sigchld_cnt = 0;

voida
sigchld_hdlr(int signo)
{
        ++sigchld_cnt;
}

int
main(int ac, char **av)
{
        int looping = 1;
        int child_cnt = 0;
        int status;

        signal(SIGCHLD, sigchld_hdlr);

        printf("Parent PID %d\n", getpid());

        while (looping)
        {
                switch (fork())
                {
                case 0:
                        _exit(0);
                        break;
                case -1:
                        fprintf(stderr, "Problem with fork(), %d children: %s\n",
                                child_cnt, strerror(errno));
                        looping = 0;
                        break;
                default:
                        ++child_cnt;
                        break;
                }
        }

        fprintf(stderr, "Sleeping, forked %d child processes\n", child_cnt);
        fprintf(stderr, "Received %d sigchild\n", sigchld_cnt);
        sleep(10);

        looping = 1;
        do {
                int x = wait(&status);

                if (x != -1)
                        --child_cnt;
                else if (errno != EINTR) {
                        fprintf(stderr, "wait() problem %d children left: \%s\n",
                                child_cnt, strerror(errno));
                        looping = 0;
                }
        } while (looping);

        printf("%d children left, %d SIGCHLD\n", child_cnt, sigchld_cnt);

        return 0;
}

通过调用wait(2)足够的时间来“收集”所有僵尸是非常困难的。另外,接收到的SIGCHLD信号的数量与分叉的子进程的数量永远不会相同:我相信linux内核有时会为多个退出的子进程发送1 SIGCHLD。

无论如何,在我的Arch Linux笔记本电脑上,我得到了16088个子进程的分叉,并且必须是僵尸数量,因为该程序不会wait(2)在信号处理程序中进行系统调用。

在Slackware 12服务器上,我得到6076个子进程,该子进程与的值非常匹配maxproc 6079。我的用户ID还有2个其他正在运行的进程sshd和Zsh。加上上面的第一个非僵尸程序实例,使6079。

fork(2)系统调用失败,出现“资源暂时不可用”错误。我看不到任何其他证据证明什么资源不可用。如果我同时在2个不同的xterm中运行程序,我会得到一些不同的数字,但是它们的总和与我在一个xterm中运行它的数字相同。我认为它是进程表条目,交换或某些系统范围的资源,而不仅仅是任意限制。

我现在没有其他可以尝试的功能。


4

我不知道HP-UX的限制是什么。但是我可以告诉您,逻辑实现是要有一个最大大小的进程表。理论上,进程表条目的总数受进程ID范围的限制,但是大多数实现对表的大小都有限制,从而产生的最大值要小得多。大多数Unix变体对每个用户的进程数也有限制。您可以通过ulimit -u在bash中运行来查看限制。

我不希望UNIX系统对僵尸有单独的限制,而不是对进程ID(包括实际进程和僵尸)的数量没有单独的限制。因此,当进程死亡并成为僵尸时,这不会影响限制:在进程派生时分配资源(进程表中的条目),并在收获进程时释放资源。


2

我认为您可以拥有任意数量的僵尸,就像可以拥有任意数量的进程一样……?

僵尸进程最终是一个进程-在特殊状态下-然后僵尸进程受限于进程表的可用性和大小,就像常规进程一样。

发行版与发行版之间是否有不同的价值?

当然,还有其他许多参数。您不应该中继特定的大小,或者中继大小是否足以容纳许多僵尸进程。如果您有太多的僵尸,那么解决方案就不是大问题了,因为最终它会变得很满。僵尸进程本身并不坏,但是累积的僵尸进程过多则表明“行为不良”程序允许进行僵尸进程。

如果我们达到上限并尝试创建另一个僵尸会发生什么?

一旦进程表充满了常规和僵尸进程,就不能再创建新的常规进程,即使系统具有足够的资源(内存,处理器等)也是如此。唯一缺少的资源只是过程表中的单个条目。当已经在运行的程序(甚至那些“表现良好”的程序)需要创建子进程时,它们将开始失败。无法启动新程序,甚至无法运行单个命令。


Even running single commands would fail.->影响很大。
Shiplu Mokaddim '18
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.