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

Pro*_*eur 17 process kill hp-ux limit zombie-process

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

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

Bru*_*ger 12

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

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

1002 % limit
cputime         unlimited
filesize        unlimited
datasize        unlimited
stacksize       8MB
coredumpsize    0kB
memoryuse       unlimited
maxproc         16136
  ...
Run Code Online (Sandbox Code Playgroud)

那是在 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;
}
Run Code Online (Sandbox Code Playgroud)

通过调用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 中运行它一样。我假设它是进程表条目、交换或一些系统范围的资源,而不仅仅是任意限制。

我现在没有其他东西可以试穿。