一尘不染

为什么子进程必须使用“ wait()”?

linux

即使等待1的linux手册页很好地说明了您需要wait()让子进程不使其变成僵尸,但它根本无法说明原因。

我围绕一个Ever
for(;;)循环计划了我的程序(这是我的第一个多线程程序,所以请原谅我的天真),该循环启动子进程,该子进程被exec()ed淘汰,并确保自行终止。

我无法使用,wait(NULL)因为这使并行计算变得不可能,因此我可能不得不添加一个存储子pid的进程表,并且不得不使用waitpid-不是立即执行,而是经过一段时间-
这是一个问题,因为运行时间的儿童从几微秒到几分钟不等。如果我使用waitpid得太早,我的父进程将被阻塞,而当我使用得太晚时,我将被僵尸淹没,无法fork()再使用,这不仅对我的进程不利,而且会导致整个系统出现意外问题。

我可能必须编程一些使用最大子代数的逻辑,并在达到该最大数时阻止父代-
但这不是必须的,因为大多数子代会很快终止。我可以想到的另一个解决方案(创建一个两层的父进程来生成并发子代,然后又wait为孙子代同时生成)对于我来说现在太复杂了。可能我还可以找到一个非阻塞函数来检查子代,并waitpid仅在它们终止时使用。

尽管如此,问题是:

为什么Linux完全保留僵尸?为什么我要等我的孩子?这是为了对父流程执行纪律吗?在使用Linux的几十年中,我从未从僵尸进程中获得任何有用的东西,我还没有完全了解到僵尸作为“功能”的有用性。

如果答案是父进程需要一种方法来找出发生在孩子身上的事情,那么出于上帝的缘故,没有理由将僵尸视为正常进程并仅由于存在太多僵尸进程而禁止创建非僵尸进程僵尸。在我目前正在开发的系统上,在一切停止之前,我只能产生400到500个进程(这是在我能找到的最便宜的VServer上运行的维护不佳的CentOS系统-
但仍然有400台僵尸程序不足几kB的信息)


阅读 724

收藏
2020-06-07

共1个答案

一尘不染

我可能必须添加一个存储子pid的进程表,并且必须使用waitpid(不是很明显),但是要经过一段时间后才这样做-
这是一个问题,因为子进程的运行时间从几微秒到几分钟不等。 。如果我太早使用waitpid,那么我的父进程将被阻止

请查看的文档waitpid。您可以waitpid使用该WNOHANG选项告知“
不阻止”(即,如果没有要收获的孩子,请立即返回)。此外,您无需提供waitpidPID。您可以指定-1,它将等待 任何
孩子。因此waitpid,如下所示的调用符合您的无阻塞约束和无节省pids约束:

waitpid( -1, &status, WNOHANG );

如果您 确实 不想正确处理流程的创建,则可以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 );
}

在上面的代码片段中,子进程派生出自己的子进程,立即存在,然后立即被父进程收割。孙子是孤立的,由收养init,并且将自动获得。

为什么Linux完全保留僵尸?为什么我要等我的孩子?这是为了对父流程执行纪律吗?在使用Linux的几十年中,我从未从僵尸进程中获得任何有用的东西,我还没有完全了解到僵尸作为“功能”的有用性。如果答案是父进程需要找到自己的孩子发生了什么的方法,那么,上帝的缘故,没有理由将僵尸视为正常进程,并因为存在太多僵尸进程而禁止创建非僵尸进程僵尸。

您还建议如何有效地检索流程的退出代码?问题在于PID
<=>退出代码(等)的映射必须是一对一的。如果内核在退出,收获或未收获时立即释放了该进程的PID,然后新进程继承了相同的PID并退出,那么如何处理为一个PID存储两个代码?感兴趣的进程将如何检索第一个进程的退出代码?不要以为
没有人 在乎退出代码是因为您不在乎。您认为是滋扰/错误的东西被广泛认为是有用和干净的。

在我目前正在开发的系统上,在一切停止之前,我只能产生400到500个进程(这是在我能找到的最便宜的VServer上运行的维护不佳的CentOS系统-
但仍然有400台僵尸程序不足几kB的信息)

关于使人们普遍接受的内核行为成为对维护不佳/廉价系统的明显挫败感的替罪羊,这似乎是不对的。

通常,最大进程数仅受内存限制。您可以通过以下方式查看限额:

cat /proc/sys/kernel/threads-max
2020-06-07