收养孩子意味着什么?

时间:2019-11-15 23:08:19

标签: c zombie-process waitpid

我刚刚做了一个演讲,总结为:

收获

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

    为父级提供退出状态信息

    内核然后删除僵尸子进程

因此,我了解通过在父进程中调用waitwaitpid来进行收割,然后内核删除了僵尸进程。如果确实是这种情况,那么只有在调用waitwaitpid时才进行收割,为什么子进程在返回theor入口函数后实际上消失了-我的意思是确实确实好像子进程已被收获,因此即使父进程可能没有在等待,也不会浪费资源。

“收割”仅在调用waitwaitpid时才可能吗?只要进程返回并退出其入口函数(我假设所有进程都这样做),它们是否就“收获”了?谈论“收获”好像有什么特殊的意义是什么?

2 个答案:

答案 0 :(得分:2)

子进程退出时不能完全“消失”。它不再作为正在运行的进程而存在,并且它的大部分/所有资源(内存,打开的文件等)都已释放,但是它仍然保留在进程表中。它保留在进程表中,因为这是存储其退出状态的地方,以便父级可以通过调用wait变体之一来检索它。如果父项未能调用wait,则进程表条目会停留在周围-这就是使它成为“僵尸”的原因。

我说过,它的大部分/所有资源都已释放,但是肯定仍在使用的一种资源是进程表插槽。

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

如果父级最终退出(从未调用wait),则子级将由祖父母继承,这通常是像shell或init这样的“主”进程,该进程通常会执行致电wait,这将最终“收获”可怜的年轻僵尸。

所以,是的,正如您的演讲所述,父母正确“收获”孩子的唯一方法是调用wait函数之一。 (或者退出,但是如果父母要长时间奔跑,那就太糟糕了。)

答案 1 :(得分:2)

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

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

另一种方法是执行双叉创建孙子进程。这样做时,“父母”会在调用wait()之后进行阻塞fork()。然后,子级执行另一个fork()来创建孙级,然后立即退出,从而使父级解除阻止。现在,孙子完成了真正的工作,并被init进程自动收割。