在UNIX中,当父进程消失时,我认为所有子进程都会将init重置为其父进程。这不是一直都是正确的吗?有例外吗?
答案1
2014 年写的三个答案,都说在 Unices 和 Linux 中,进程无一例外地被重新设置为进程#1。三个错误答案。 ☺
作为不锈钢说,引用之一其他在这里回答所以我不会再引用它,孤儿的父进程被设置为实现定义的过程。 Cristian Ciupitu 查阅 Linux 文档以了解实现定义的内容是正确的。但他被该文件误导了,该文件不一致且不是最新的。
在写这三个答案的两年前,以及三年前第一次写这个答案时,Linux 内核发生了变化。 systemd 开发人员添加了进程将自己设置为“子收割者”的功能。从 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 内核的那个)、upstart 和 nosh——service-manager
已经在使用它了。
如果这样的守护进程管理程序不是进程#1,并且它生成一项服务,例如交互式登录会话,并且在该会话中,它会执行fork()
试图通过加倍来“守护”的(相当错误的)技巧,那么一个进程将最终成为守护进程管理程序的子进程,而不是进程 #1 的子进程。当然,期望能够从登录会话中直接生成守护进程是一个根本性的错误。但这是另一个答案。
进一步阅读
- 乔纳森·科贝特 (2012-03-28)。3.4 合并窗口第2部分。 LWN。
- 《4.各种核心变化》。Linux 3.4。内核新手。 2012年。
- 守护进程和暴发户。内科科内科。 2014年11月12日。
- 伦纳特·珀特林 (2012-03-23)。prctl:添加 PR_{SET,GET}_CHILD_SUBREAPER 以允许简单的进程监督。 linux/kernel/git/torvalds/linux.git。
- 马修·狄龙 (2014)。添加reapctl()系统调用来管理子进程 (3) -> procctl()。蜻蜓.git。
procctl()
。 DragonFly BSD 手册页。 §2.- DragonFly BSD 4.2 发行说明。 2015年7月29日。
- 康斯坦丁·别洛乌索夫 (2014-12-01)。加工收割机。 freebsd-arch 邮件列表。
答案2
根据exit
The Single UNIX® 规范第 2 版的手册页:
所有调用进程的现有子进程和僵尸进程的父进程 ID 都设置为依赖于实现的系统进程的进程 ID。也就是说,这些进程是由特殊的系统进程继承的。
对于大多数 Unix 变体,该特殊进程是init
(PID 1)。
Linuxwait(2)
手册页证实了这一点:
如果父进程终止,则其“僵尸”子进程(如果有)将被 init(8) 采用,它会自动执行等待以删除僵尸进程。
自由BSDwait(2)
, 网络BSDwait(2)
, 开放BSDwait(2)
和 Mac OS Xwait(2)
手册页也证实了这一点:
如果父进程在没有等待其所有子进程终止的情况下终止,则剩余的子进程将被分配父进程 1 ID(init 进程 ID)。
Oracle Solaris 11.1wait(3C)
手册页也证实了这一点:
如果父进程没有等待其子进程终止就终止,则每个子进程的父进程ID设置为1,初始化进程继承子进程;看
Intro(2)
。
答案3
答案4
我不相信是这样。它总是进入 init 进程。