Joh*_*ith 49 process fork exit init
我研究 Linux 内核行为已经有一段时间了,我一直很清楚:
当一个进程终止时,它的所有子进程都会返回给该
init进程(PID 1),直到它们最终终止。
然而,最近,一个比我在内核方面更有经验的人告诉我:
当一个进程退出时,它的所有子进程也会死亡(除非你
NOHUP在这种情况下使用它们返回到init)。
现在,即使我不相信这一点,我仍然编写了一个简单的程序来确保它。我知道我不应该依赖时间 ( sleep) 进行测试,因为它完全取决于进程调度,但对于这个简单的情况,我认为这已经足够了。
int main(void){
printf("Father process spawned (%d).\n", getpid());
sleep(5);
if(fork() == 0){
printf("Child process spawned (%d => %d).\n", getppid(), getpid());
sleep(15);
printf("Child process exiting (%d => %d).\n", getppid(), getpid());
exit(0);
}
sleep(5);
printf(stdout, "Father process exiting (%d).\n", getpid());
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
这是程序的输出,ps每次printf通话时都有相关的结果:
$ ./test &
Father process spawned (435).
$ ps -ef | grep test
myuser 435 392 tty1 ./test
Child process spawned (435 => 436).
$ ps -ef | grep test
myuser 435 392 tty1 ./test
myuser 436 435 tty1 ./test
Father process exiting (435).
$ ps -ef | grep test
myuser 436 1 tty1 ./test
Child process exiting (436).
Run Code Online (Sandbox Code Playgroud)
现在,正如您所看到的,这与我预期的一样。孤儿进程 (436) 返回给init(1),直到它死亡。
但是,是否有任何基于 UNIX 的系统默认情况下不应用此行为?是否有任何一个进程的死亡立即触发其所有子进程的死亡的系统?
Gil*_*il' 74
当一个进程退出时,它的所有子进程也会死亡(除非你使用 NOHUP,在这种情况下它们会返回到 init)。
这是错误的。大错特错。说这话的人要么是错误的,要么是将特定情况与一般情况混淆了。
进程的死亡可以通过两种方式间接导致其子进程的死亡。它们与终端关闭时发生的情况有关。当终端消失时(过去是因为调制解调器挂断串行线被切断,现在通常是因为用户关闭了终端仿真器窗口),一个 SIGHUP 信号被发送到在该终端中运行的控制进程——通常,初始外壳启动在那个终端。外壳通常通过退出来对此做出反应。在退出之前,用于交互使用的 shell 将 HUP 发送到它们启动的每个作业。
从外壳启动作业并nohup中断 HUP 信号的第二个来源,因为作业将忽略该信号,因此不会在终端消失时被告知终止。其他阻止 HUP 信号从 shell 传播到作业的方法包括使用 shell 的disown内置命令(如果作业从 shell 的作业列表中删除)和双分叉(shell 启动一个子进程,然后启动子进程)并立即退出;外壳不知道它的孙子)。
同样,在终端中启动的作业死亡不是因为它们的父进程(shell)死亡,而是因为它们的父进程在被告知要杀死它们时决定杀死它们。终端中的初始 shell 死亡不是因为它的父进程死亡,而是因为它的终端消失了(这可能是也可能不是巧合,因为终端是由终端仿真器提供的,它是 shell 的父进程)。
小智 12
当一个进程退出时,它的所有子进程也会死亡(除非你使用 NOHUP,在这种情况下它们会返回到 init)。
如果进程是会话领导者,这是正确的。当会话领导者死亡时,会向该会话的所有成员发送 SIGHUP。实际上,这意味着它的孩子和他们的后代。
一个进程通过调用使自己成为会话领导者setsid。贝壳使用这个。