하위 프로세스가 상위 프로세스와 함께 종료되는 UNIX 변형이 있습니까?

하위 프로세스가 상위 프로세스와 함께 종료되는 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 기반 시스템이 있습니까? 프로세스가 종료되면 즉시 모든 하위 프로세스가 종료되는 시스템이 있습니까?

답변1

프로세스가 종료되면 모든 하위 프로세스도 종료됩니다(NOHUP을 사용하여 init로 돌아가지 않는 한).

이것은 잘못된 것입니다. 정말 틀렸어요. 이렇게 말하는 사람은 틀렸거나 특정 상황을 일반적인 상황과 혼동하는 것입니다.

프로세스가 죽는 방법에는 두 가지가 있습니다.간접적으로그 결과 그의 자녀들이 죽게 되었습니다. 터미널이 닫힐 때 일어나는 일과 관련이 있습니다. SIGHUP 신호는 터미널이 사라질 때 발생합니다. (역사적으로는 모뎀 끊김으로 인해 직렬 회선이 끊어졌기 때문에 현재는 일반적으로 사용자가 터미널 에뮬레이터 창을 닫았기 때문입니다.)전송 된도착하다제어 프로세스이 터미널에서 실행 - 일반적으로 초기 쉘은 이 터미널에서 시작됩니다. 쉘은 일반적으로 종료하여 이에 반응합니다. 대화형 사용을 위한 셸은 종료하기 전에 시작하는 각 작업에 HUP를 보냅니다.

셸에서 작업을 시작하면 nohup작업이 신호를 무시하므로 터미널이 사라질 때 종료하라는 메시지가 표시되지 않기 때문에 HUP 신호의 두 번째 소스가 파괴됩니다. 셸에서 작업으로의 HUP 신호 전파를 중단하는 다른 방법에는 disown가능한 경우 셸의 내장 기능을 사용하는 것(작업이 셸의 작업 목록에서 제거됨) 및 이중 분기(셸이 다음을 실행하는 하위 프로세스를 시작함)가 포함됩니다. 자체적으로 자식 프로세스를 시작하고 즉시 종료됩니다. 쉘은 손자 프로세스에 대해 알지 못합니다.

마찬가지로 터미널에서 시작된 작업은 상위 프로세스(셸)가 종료되기 때문에 종료되는 것이 아니라 해당 작업을 종료하라는 지시를 받았을 때 해당 상위 프로세스가 해당 작업을 종료하기로 결정하기 때문에 종료됩니다. 터미널의 초기 쉘은 부모 프로세스가 죽기 때문이 아니라 터미널이 사라지기 때문에 죽습니다(터미널이 쉘 부모 프로세스의 터미널 에뮬레이터에 의해 제공되기 때문에 이것은 우연일 수도 있고 아닐 수도 있습니다).

답변2

프로세스가 종료되면 모든 하위 프로세스도 종료됩니다(NOHUP을 사용하여 init로 돌아가지 않는 한).

프로세스가 세션 리더인 경우 이는 맞습니다. 세션 리더가 사망하면 SIGHUP이 세션의 모든 구성원에게 전송됩니다. 실제로 이는 자녀와 그 후손을 의미합니다.

프로세스는 를 호출하여 자신을 세션 리더로 만듭니다 setsid. 이것을 껍질에 사용하세요.

답변3

대답에서 놓쳤던 죽어가는 부모와 약간 관련이 있습니다. 프로세스가 더 이상 읽기 프로세스가 없는 파이프에 쓸 때 SIGPIPE를 받습니다. SIGPIPE의 표준 작업은 종료입니다.

이로 인해 실제로 프로세스가 종료됩니다. 실제로 이는 yes프로그램을 종료하는 표준 방법입니다.

내가 실행하면

(yes;echo $? >&2)|head -10

내 시스템에서 대답은 다음과 같습니다.

y
y
y
y
y
y
y
y
y
y
141

141은 실제로 128+SIGPIPE입니다.

   SIGPIPE      13       Term    Broken pipe: write to pipe with no
                                 readers

에서 man 7 signal.

답변4

따라서 위의 포스터가 말하는 것은 아이들이 죽는 것이 아니라 부모가 그들을 죽이는 것(또는 그들에게 종료 신호를 보내는 것)이라는 것입니다. 따라서 부모가 (1) 모든 자식의 기록을 유지하고 (2) 모든 자식에게 신호를 보내도록 프로그래밍하면 원하는 것을 얻을 수 있습니다.

이것이 쉘이 하는 일이고, 부모 프로세스가 해야 할 일입니다. 자식을 죽일 수 있는 충분한 제어권을 가지려면 부모에서 HUP 신호를 포착해야 할 수도 있습니다.

관련 정보