我曾经使用 HP-UX 系统,老管理员告诉我系统上可以拥有的僵尸进程数量有上限,我相信是 1024。
- 这是一个硬事实上限吗?我认为你可以有任意数量的僵尸,就像你可以有任意数量的进程一样......?
- 不同发行版的价值是否不同?
- 如果我们达到上限并尝试创建另一个僵尸会发生什么?
答案1
我没有可用的 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
...
这是在 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 中运行它时的数字相同。我假设它是进程表条目、交换或某些系统范围的资源,而不仅仅是任意限制。
我现在没有其他东西可以尝试。
答案2
我不知道 HP-UX 的限制是什么。不过,我可以告诉您,逻辑实现是拥有一个具有最大大小的进程表。理论上,进程表条目的总数受到进程 ID 范围的限制,但大多数实现都有表的大小限制,这会产生更小的最大值。大多数 Unix 变体也对每个用户的进程数量有限制;您可以通过在 bash 中运行来查看限制ulimit -u
。
我不希望 UNIX 系统对僵尸有单独的限制,而不是对进程 ID 的数量(包括实际进程和僵尸)有单独的限制。因此,当进程死亡并成为僵尸进程时,这不会影响限制:资源(进程表中的条目)在进程分叉时分配,并在进程回收时释放。
答案3
我认为你可以有任意数量的僵尸,就像你可以有任意数量的进程一样......?
僵尸进程最终是一个处于特殊状态的进程,然后僵尸进程受到进程表的可用性和大小的限制,至于常规的流程。
不同发行版的价值是否不同?
当然,还有许多其他参数。您不应该依赖特定的大小,或者它是否足够大以容纳许多僵尸进程。如果僵尸太多,那么解决方案就不是一张大桌子,因为它最终会满的。僵尸进程本身并不坏,但是累积太多僵尸进程表明存在允许僵尸进程的“行为不良”程序。
如果我们达到上限并尝试创建另一个僵尸会发生什么?
一旦进程表充满了常规进程和僵尸进程,就无法创建新的常规进程,即使系统有足够的资源(内存、处理器等)。唯一缺少的资源只是进程表中的一个条目。已经在运行的程序——即使是那些“表现良好”的程序——在需要创建子进程时也会开始失败。新程序无法启动,甚至运行单个命令也会失败。