자식 프로세스가 부모와 함께 죽는 UNIX 변형이 있습니까?


41

나는 꽤 오랫동안 리눅스 커널 동작을 연구 해 왔으며 항상 나에게 분명하다.

프로세스가 죽으면 모든 자식은 프로세스가 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 기반 시스템이 있습니까? 프로세스의 사망이 모든 아동의 사망을 즉시 유발할 수있는 시스템이 있습니까?

답변:


68

프로세스가 종료되면 모든 자식도 죽습니다 (NOHUP을 사용하지 않으면 다시 초기화됩니다).

이것은 잘못이다. 죽었어 그 말을 잘못한 사람이나 일반적인 상황과 특정 상황을 혼동 한 사람.

프로세스 의 죽음이 간접적으로 자녀의 죽음을 초래할 수있는 두 가지 방법이 있습니다. 터미널을 닫을 때 발생하는 상황과 관련이 있습니다. 터미널이 사라지면 (사전에는 사용자가 터미널 에뮬레이터 창을 닫았 기 때문에 모뎀 행업으로 인해 직렬 회선이 끊어 졌기 때문에 SIGHUP 신호 해당 터미널에서 실행중인 제어 프로세스로 전송 됩니다. 일반적으로 초기 쉘이 시작됨) 그 터미널에서. 쉘은 일반적으로 종료하여 이에 반응합니다. 종료하기 전에 대화식으로 사용하기위한 쉘은 시작한 각 작업에 HUP를 보냅니다.

쉘에서 작업을 시작하면 작업 nohup이 신호를 무시하므로 터미널이 사라질 때 죽으라는 지시를받지 않기 때문에 HUP 신호의 두 번째 소스 가 중단됩니다. 쉘에서 작업으로의 HUP 신호 전파를 차단하는 다른 방법에는 쉘 disown내장 기능이있는 경우 내장 된 기능 사용 (작업이 쉘의 작업 목록에서 제거됨) 및 이중 분기 (쉘이 하위를 실행하는 하위를 시작 함)가 포함됩니다. 껍질은 손자에 대한 지식이 없다).

다시 말하지만, 터미널에서 시작된 작업은 부모 프로세스 (쉘)가 죽기 때문이 아니라 부모 프로세스가 작업을 종료하라는 명령을 받으면 작업을 종료하기로 결정하기 때문에 죽습니다. 그리고 터미널의 초기 쉘은 부모 프로세스가 죽기 때문이 아니라 터미널이 사라지기 때문에 죽습니다 (우연히 터미널이 쉘의 부모 프로세스 인 터미널 에뮬레이터에 의해 제공되기 때문일 수도 있고 아닐 수도 있습니다).


1
제어 그룹이있는 세 번째 방법이 있습니다. 내가 아는 것은 systemd가 그것을 사용하여 클린 킬을 시행한다는 것입니다.
o11c

5
@JanHudec 나는 당신이 혼란 있다고 생각 nohup과 함께 disown. disown는 작업 테이블에서 실행중인 작업을 제거하는 일부 쉘에 내장되어 있으며 (와 같은 인수 사용 %1) 쉘의 주요 부작용은 쉘이 SIGHUP을 하위 프로세스로 보내지 않는다는 것입니다. nohupSIGHUP을 무시하고 다른 작업을 거의 수행하지 않는 외부 유틸리티이며 명령 행에서 전달 된 명령을 시작합니다.
Gilles 'SO- 악마 그만해'

@Gilles : 아니요, 아닙니다. 그러나 strace nohup를 보면 실제로 exec명령을 내리기 전에 신호를 무시합니다 .
Jan Hudec

답변 주셔서 감사합니다! 특히 모뎀 끊기와 관련된 약간의 역사적 배경이 마음에 들었습니다. 나는이 시간 내내 커널을 오해하고 있다고 걱정하기 시작했다.
John WH Smith

3
또한 SIGHUP의 기본 신호 핸들러가 종료되므로 SIGHUP을 수신하면 프로그램이 종료됩니다. 그러나 모든 프로그램은 자체 SIGHUP 핸들러를 구현하여 상위 쉘이 SIGHUP을 보낼 때 종료되지 않을 수 있습니다.
slebetman

12

프로세스가 종료되면 모든 자식도 죽습니다 (NOHUP을 사용하지 않으면 다시 초기화됩니다).

프로세스가 세션 리더 인 경우 올바른 것입니다. 세션 리더가 사망하면 SIGHUP이 해당 세션의 모든 구성원에게 전송됩니다. 실제로 그것은 그것의 아이들과 그들의 자손을 의미합니다.

프로세스는를 호출하여 세션 리더가됩니다 setsid. 껍질은 이것을 사용합니다.


방금 이것에 대해 테스트를 실행했지만 설명하는 동작을 재현 할 수 없었습니다 ... 프로세스를 생성하고 새 세션 ( fork, 부모 프로세스 종료 setsid)을 제공 하고이 새로운 세션에 다른 어린이를 포크했습니다. 그러나 부모 프로세스 (새 세션 리더)가 사망하면 자식은 SIGHUP을받지 못하고 init종료 될 때까지 연결됩니다 .
John WH Smith

에서 setpgid(2)맨 페이지 : 세션이 제어 터미널을 가지고 있으며, 해당 터미널의 CLOCAL 플래그가 설정되지 않으며, 터미널 끊기가 발생하면, 세션 리더는 SIGHUP을 전송됩니다. 세션 리더가 종료되면 SIGHUP 신호도 제어 터미널의 포 그라운드 프로세스 그룹에있는 각 프로세스로 전송됩니다.
ninjalj

1
@ninjalj 그렇다면 세션 리더가 터미널의 제어 프로세스 인 경우에만이 대답이 유효하다고 생각합니다. 터미널과 관계없이 표준 세션 리더는 자식을 죽이지 않습니다. 맞습니까?
John WH Smith 12

-1

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

이것이 쉘이하는 일이며 부모 프로세스가하는 일입니다. 부모에게 HUP 신호를 포착해야 어린이를 죽일 수있는 충분한 통제력을 가질 수 있습니다.


많은 원인이 부모를 죽게 만들 수 있습니다. 예를 들어 부모가 SIGKILLed 인 경우 어린이의 생존을 막을 방법이 없습니다.
Emil Jeřábek

-1

죽어가는 부모와 약간 관련이있는 답변에서 1 비트가 누락되었습니다. 프로세스가 더 이상 읽기 프로세스가없는 파이프에 쓸 때 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.


2
그러나 파이프에서 읽는 프로세스가 반드시 부모는 아닙니다. 따라서 이것은 실제로 질문이 제기하는 것과는 매우 다른 경우입니다.
Barmar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.