web-dev-qa-db-ja.com

子プロセスが親プロセスで停止するUNIXバリアントはありますか?

私はかなり以前から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;
}

これはプログラムの出力で、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).

さて、ご覧のとおり、これは私が期待したとおりに動作します。孤立プロセス(436)は、死ぬまでinit(1)に戻されます。

ただし、この動作がデフォルトで適用されないUNIXベースのシステムはありますか?プロセスが停止するとすぐにすべての子プロセスが停止するシステムはありますか?

46
John WH Smith

プロセスが終了すると、その子もすべて終了します(ただし、Nohupを使用する場合を除きます)。

これは間違っています。間違いだ。それを誤解した、または一般的なケースと特定の状況を混同したと言った人。

プロセスの終了が間接的にその子の死亡を引き起こす可能性がある2つの方法があります。これらは、ターミナルが閉じられたときに何が起こるかに関連しています。端末が消えたとき(歴史的には、モデムのハングアップが原因でシリアル回線が切断されたため、現在では通常、ユーザーが端末エミュレーターウィンドウを閉じたため)、SIGHUPシグナル 送信される制御プロセス その端末で実行中-通常、最初のシェルはその端末で開始されました。シェルは通常、終了することによってこれに反応します。終了する前に、インタラクティブな使用を目的としたシェルは、開始した各ジョブにHUPを送信します。

Nohupを使用してシェルからジョブを開始すると、HUPシグナルの2番目のソースが中断されます。これは、ジョブがシグナルを無視するため、端末が消えても死ぬように指示されないためです。シェルからジョブへのHUP信号の伝播を中断する他の方法には、シェルのdisownビルトインがある場合(そのジョブはシェルのジョブリストから削除されます)、ダブルフォーク(シェルが起動する)を使用することが含まれます自分の子を起動してすぐに終了する子;シェルは孫の知識を持ちません)。

繰り返しになりますが、ターミナルで開始されたジョブは、その親プロセス(シェル)が終了したためではなく、それらを強制終了するように指示されたときに親プロセスが強制終了することを決定したためです。また、ターミナルの最初のシェルは、親プロセスが終了したためではなく、ターミナルが消えたために終了します(これは、ターミナルがシェルの親プロセスであるターミナルエミュレーターによって提供されたことが原因である場合も、そうでない場合もあります)。

プロセスが終了すると、その子もすべて終了します(ただし、Nohupを使用する場合を除きます)。

プロセスがセッションリーダーである場合、これは正しいです。セッションリーダーが死亡すると、そのセッションのすべてのメンバーにSIGHUPが送信されます。実際には、その子供とその子孫を意味します。

プロセスはsetsidを呼び出すことにより、それ自体をセッションリーダーにします。シェルはこれを使用します。

12
Dennis