为什么我必须为子进程`wait()`?

Rob*_*y75 15 linux fork

即使等待1的linux手册页很好地解释了你需要wait()为他们的子进程不要变成僵尸,它根本不说明原因.

我计划了我的程序(这是我的第一个多线程程序,所以请原谅我的天真)围绕一个for(;;)永远的循环启动子进程,它们被exec()废弃并且肯定会自行终止.

我无法使用,wait(NULL)因为这使得并行计算变得不可能,因此我可能不得不添加一个存储子pids的进程表,并且必须使用waitpid- 不是无聊的,但经过一段时间后 - 这是一个问题,因为运行时间孩子们从几微秒到几分钟不等.如果我使用waitpid得太早,我的父进程将被阻止,当我太晚使用它时,我会被僵尸淹没,不能fork()再这样了,这不仅对我的进程有害,而且会导致整个系统出现意外问题.

我可能不得不编写一些使用一些最大数量的子节点的逻辑,并在达到该数量时阻止父节点 - 但这不应该是必要的,因为大多数子节点很快终止.我能想到的另一个解决方案(创建一个双层父进程,产生并发子进程,而这些进程同时产生和wait为孙子进行生成)对我来说太复杂了.可能我还可以找到一个非阻塞功能来检查孩子,并且waitpid只有当他们终止时才使用.

不过问题是:

为什么Linux会保留僵尸?为什么我要等我的孩子?这是否对父进程强制执行纪律?在使用Linux的几十年中,我从来没有从僵尸进程中获得任何有用的东西,我不太了解僵尸作为"特征"的用处.

如果答案是父进程需要有办法找出他们的孩子发生了什么,那么为了上帝的缘故,没有理由把僵尸算作正常的进程并且禁止创建非僵尸进程只是因为有太多僵尸.在我正在开发的系统上,我只能生成400到500个进程才能停止一切(这是一个维护得很差的CentOS系统,运行在我能找到的最便宜的VServer上 - 但仍然有400个僵尸不到几KB的信息)

Chr*_*lan 11

我可能不得不添加一个存储子pids的进程表,并且必须使用waitpid - 不是随便的,但经过一段时间后 - 这是一个问题,因为孩子们的运行时间从几微秒到几分钟不等.如果我太早使用waitpid,我的父进程将被阻止

查看文档waitpid.您可以waitpid使用该WNOHANG选项告诉NOT阻止(即,如果没有孩子需要立即返回).而且,您不需要提供waitpidPID.你可以指定-1,它会等待任何孩子.因此,调用waitpid如下适合您的无阻塞约束和no-saving-pids约束:

waitpid( -1, &status, WNOHANG );
Run Code Online (Sandbox Code Playgroud)

如果你真的不想正确处理创造过程,那么你可以init通过分叉两次,收割孩子,并给予exec孙子来给予收割责任:

pid_t temp_pid, child_pid;
temp_pid = fork();
if( temp_pid == 0 ){
    child_pid = fork();
    if( child_pid == 0 ){
        // exec()
        error( EXIT_FAILURE, errno, "failed to exec :(" );
    } else if( child_pid < 0 ){
        error( EXIT_FAILURE, errno, "failed to fork :(" );
    }
    exit( EXIT_SUCCESS );
} else if( temp_pid < 0 ){
    error( EXIT_FAILURE, errno, "failed to fork :(" );
} else {
    wait( temp_pid );
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码片段中,子进程分叉自己的子进程,立即存在,然后由父进程立即获取.孙子是孤儿,被收养init,并将自动收获.

为什么Linux会保留僵尸?为什么我要等我的孩子?这是否对父进程强制执行纪律?在使用Linux的几十年中,我从来没有从僵尸进程中获得任何有用的东西,我不太了解僵尸作为"特征"的用处.如果答案是父进程需要有办法找出他们的孩子发生了什么,那么为了上帝的缘故,没有理由把僵尸算作正常的进程并且禁止创建非僵尸进程只是因为有太多僵尸.

您如何建议可以有效地检索进程的退出代码?问题是PID <=>退出代码(等)的映射必须是一对一的.如果内核在退出时立即释放了进程的PID,是否收到了,然后新进程继承了相同的PID并退出,您将如何处理为一个PID存储两个代码?感兴趣的进程如何检索第一个进程的退出代码?不要以为没有人关心退出代码只是因为你没有.你认为是一个令人讨厌的东西被广泛认为是有用和干净的.

在我正在开发的系统上,我只能生成400到500个进程才能停止一切(这是一个维护得很差的CentOS系统,运行在我能找到的最便宜的VServer上 - 但仍然有400个僵尸不到几KB的信息)

将一个被广泛接受的内核行为作为对一个维护不善/廉价系统明显受挫的替罪羊的事情似乎并不正确.

通常,您的最大进程数仅受内存限制.你可以看到你的限制:

cat /proc/sys/kernel/threads-max
Run Code Online (Sandbox Code Playgroud)