Answers:
2014年写的三个答案都说,在Unices和Linux中,该流程无一例外地被复制为#1。三个错误答案。☺
就像SUS所说的那样,在这里用其他答案中的一个引用,这样我就不再引用它了。孤儿的父进程设置为实现定义的进程。Cristian Ciupitu有权查阅Linux文档来查看实现定义。但是他被这份文件所误导,这是不一致的并且不是最新的。
在编写这三个答案的两年前,直到三年前第一次编写此答案时,Linux内核发生了变化。系统化的开发人员增加了流程将自己设置为“次级收货人”的能力。从Linux 3.4开始,进程可以prctl()
使用该PR_SET_CHILD_SUBREAPER
选项发出系统调用,结果,它们(而不是进程1)将成为其任何孤立后代进程的父级。的手册页prctl()
是最新的,但是其他手册页尚未更新并保持一致。
在版本10.2中,FreeBSD获得了相同的功能,procctl()
使用PROC_REAP_ACQUIRE
和PROC_REAP_RELEASE
选项扩展了其现有的系统调用。它采用了DragonFly BSD的这种机制。并在4.2版中获得了该功能,该名称最初是reapctl()
在开发过程中命名为,但后来改名为procctl()
。
因此,有一些例外,并且是相当突出的例外:在Linux,FreeBSD / PC-BSD和DragonFly BSD上,孤儿的父进程设置为标记为子收割者的子进程的最接近的祖先进程,或称为进程#1。如果没有祖先收货过程。各种守护程序监督实用程序(包括systemd(开发人员首先将其放入Linux内核的程序),暴发户和nosh service-manager
)已经利用了这一功能。
如果这样的守护进程的主管没有处理#1,并产生一个服务,如交互式登录会话,并在会话中的一个不通过双试图“守护进程”的(相当刚愎自用)招fork()
ING,那么一个人的过程将最终成为守护程序主管的孩子,而不是进程1的孩子。当然,期望能够从登录会话中直接生成守护程序是一个根本错误。但这是另一个答案。
procctl()
。DragonFly BSD手册页。§2。根据exit
The SingleUNIX®Specification版本2 的手册页:
所有调用进程的现有子进程和僵尸进程的父进程ID都设置为与实现相关的系统进程的进程ID。即,这些过程是由特殊系统过程继承的。
对于大多数Unix变体,该特殊过程是init
(PID 1)。
Linux wait(2)
手册页对此进行了确认:
如果父进程终止,则init(8)将采用其“僵尸”子级(如果有的话),它将自动执行等待以删除僵尸。
FreeBSD wait(2)
,NetBSD wait(2)
,OpenBSD wait(2)
和Mac OS X wait(2)
手册页也对此进行了确认:
如果父进程在不等待其所有子进程终止的情况下终止,则将为其余子进程分配父进程1 ID(初始化进程ID)。
Oracle Solaris 11.1 wait(3C)
手册页也对此进行了确认:
如果父进程在不等待其子进程终止的情况下终止,则每个子进程的父进程ID设置为1,而初始化进程继承子进程;见
Intro(2)
。
我不相信 它总是进入初始化过程。