当前位置: 首页 > 面试题库 >

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

林祯
2023-03-14
问题内容

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

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

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

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

尽管如此,问题是:

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

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


问题答案:

我可能必须添加一个存储子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


 类似资料:
  • 本文向大家介绍为什么必须使用Twitter进行联网,包括了为什么必须使用Twitter进行联网的使用技巧和注意事项,需要的朋友参考一下 如果我们能够在线开发有价值的业务网络,那真是太棒了? 是的,通过“ Twitter”可以实现–实时通信枢纽成为一个出色的业务网络平台。通过在这种快节奏的环境中改进和实施我们的社交网络技能,Twitter可以用作构建强大的业务网络的起点。 对于Twitter的网络,

  • 关于在最新版本的GCC和Clang中编译有几个问题:实验::filessystems链接器错误 但是现在< code>filesystem已经被c 17接受,所以不再需要< code>experimental或< code>-lstdc fs标志,对吗? 错了,我甚至不能 只给了我< code >实验版本,我怎么能包括正式接受的版本呢?

  • 问题内容: 当我使用关键字访问类中的非静态变量时,Java不会给出任何错误。但是当我不使用它时,Java会给出一个错误。为什么要使用? 我知道什么时候应该正常使用,但是这个示例与正常用法大不相同。 例: 问题答案: 首先声明变量,然后赋值。该类与此相同: 您无法执行此操作的原因是,在创建对象时尚未定义,但是对象本身(即)及其所有成员变量都存在。 这是每个的说明:

  • 问题内容: 每个人都告诉我“使用super.viewDidLoad()因为它就是这样”或“我一直那样做,所以要保留它”,“如果不叫super就是错误的”等。 我只发现了一些有关Objective-C用例的主题,这些主题并没有那么启发性,但是我正在Swift 3中进行开发,所以有什么专家可以给我一个很好的详细解释吗? 这是一种良好实践的案例还是有任何隐藏的影响? 问题答案: 通常,最好为您覆盖的所有

  • 问题内容: 我希望这个问题不会太笼统。我知道,要在您上进行绘制,您需要重写该方法,并将所有绘制代码​​放入该方法中。我的问题是为什么!为什么Java似乎不允许/提供使用诸如或方法的绘图?在delphi中,一切都变得如此简单。一定有一个原因我无法弄清楚。 问题答案: 那是因为这就是它的工作方式。它是以此方式设计的。但是我想你的问题是关于“为什么” 请记住,Swing大约在15年前问世。批评之一是该A

  • 问题内容: 结合使用带有ReactJS的ES5开发,可以将组件描述如下: 在此的示例引用对象本身,这是预期的自然行为。 题 我的问题是: 如何使用ES6创建组件? 知道在JavaScript中使用new运算符时会引用实例化对象本身,因此有人可以告诉我使用bind的真正目的是什么?这和React的内部机制有关吗? 问题答案: 只是核心javascript。这是绑定事件的工作方式。这不是一个React