【问题标题】:What does reaping children imply?收割孩子意味着什么?
【发布时间】:2020-03-12 03:02:26
【问题描述】:

我刚刚做了一个讲座,总结如下:

收获

  • 由父级对终止的子级执行(使用 wait 或 waitpid)

    为父级提供退出状态信息

    内核然后删除僵尸子进程

所以我知道收割是通过从父进程调用waitwaitpid 来完成的,之后内核会删除僵尸进程。如果情况确实如此,那么只有在调用waitwaitpid 时才进行收割,为什么子进程在返回或入口函数后实际上消失了——我的意思是确实看起来子进程已经收获,因此即使父进程可能没有等待,也不会浪费任何资源。

那么只有在调用waitwaitpid 时才可能“收割”?只要进程返回并退出其入口函数(我假设所有进程都这样做),进程是否就被“收割”了 - 将“收割”说成是特别的东西有什么意义?

【问题讨论】:

    标签: c zombie-process waitpid


    【解决方案1】:

    子进程在退出时并没有完全“消失”。它不再作为一个正在运行的进程存在,并且它的大部分/所有资源(内存、打开的文件等)都被释放,它仍然保留在进程表中。它保留在进程表中,因为这是存储其退出状态的位置,因此父级可以通过调用wait 变体之一来检索它。如果父进程调用wait 失败,进程表条目会一直存在——这就是它成为“僵尸”的原因。

    我说它的大部分/所有资源都被释放了,但肯定仍在消耗的一个资源是那个进程表槽。

    只要(死)子的父级存在,内核就不会知道父级最终不会调用wait,因此进程表槽必须留在那里,以便最终调用wait(如果有的话)可以返回正确的退出状态。

    如果父进程最终退出(从未调用wait),子进程将由祖父进程继承,祖父进程通常是类似于shell 或init 的“主”进程,通常会调用wait这将最终“收割”可怜的年轻僵尸。

    所以,是的,正如您的讲座所说,父母正确“收获”孩子的唯一方法是调用wait 函数之一。 (或者退出,但如果父母长期运行,那就很糟糕了。)

    【讨论】:

    • 而将其从进程表中删除的唯一方法是调用父进程中的等待函数之一?
    • @npp> 是的。最终,如果没有其他进程处理它,它将一直到进程 1,它会执行此操作。
    【解决方案2】:

    wait*() 调用的目的是允许子进程向父进程报告状态。当子进程退出时,操作系统将状态数据保存在一个小数据结构中,直到父进程读取它。 收割在这个意义上是清理那个小数据结构。

    如果父母不关心等待孩子的状态,则可以编写代码以允许父母忽略状态,因此收获是半自动的。一种方法是忽略SIGCHLD 信号。

    另一种方法是执行双叉来创建孙进程。执行此操作时,“父级”在调用 fork() 后会阻塞 wait()。然后,孩子执行另一个fork() 来创建孙子,然后立即退出,导致父母解除阻塞。孙子现在做真正的工作,并被init 进程自动收割。

    【讨论】:

      猜你喜欢
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-30
      相关资源
      最近更新 更多