是否有任何 UNIX 变体可以让子进程与其父进程一起死亡?

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 的父进程)。

  • @JanHudec 我认为您将“nohup”与“disown”混淆了。`disown` 是某些 shell 中的内置函数,它从作业表中删除正在运行的作业(采用类似 `%1` 的参数),其主要有用的副作用是 shell 不会向子进程。`nohup` 是一个外部实用程序,它会忽略 SIGHUP(并且很少做其他事情)然后启动在其命令行上传递的命令。 (5认同)
  • 还应注意,程序在收到 SIGHUP 时退出,因为 SIGHUP 的默认信号处理程序是退出。但是任何程序都可以实现自己的 SIGHUP 处理程序,这可能会导致它在父 shell 向它发送 SIGHUP 时不退出。 (3认同)

小智 12

当一个进程退出时,它的所有子进程也会死亡(除非你使用 NOHUP,在这种情况下它们会返回到 init)。

如果进程是会话领导者,这是正确的。当会话领导者死亡时,会向该会话的所有成员发送 SIGHUP。实际上,这意味着它的孩子和他们的后代。

一个进程通过调用使自己成为会话领导者setsid。贝壳使用这个。