상위 프로세스를 종료하면 하위 프로세스가 init(PPID=1)에 연결된다는 내용을 읽었습니다.
이를 테스트하기 위해 세 개의 쉘을 생성하고 두 번째 쉘에 종료 신호를 보냈습니다.
# first process "a"
a$sh
# second process "b"
sh-5.0$ PS1=b$
b$sh
# thrid process "c"
sh-5.0$ PS1=c$
# killing process "b"
c$kill -9 $PPID
c$Killed
a$exit
a$
(killed 및 종료는 입력되지 않고 화면에 인쇄됩니다)
그러나 세 번째 쉘도 init에 연결되지 않고 종료됩니다. 왜, 누구에 의해?
답변1
귀하의 실험을 재현해 보겠습니다.
# First shell
$ echo $$
41903
# Start the second shell
$ bash
$ echo $$ $PPID
41934 41903
# Start the third shell
$ bash
$ echo $$ $PPID
41938 41934
이제 두 번째 터미널에서는 strace
실행된 시스템 호출과 세 번째 셸에서 처리되는 신호를 모니터링하겠습니다. 셸은 입력을 기다리는 동안 차단됩니다.
$ strace -p 41938
strace: Process 41938 attached
pselect6(1, [0], NULL, NULL, NULL, {[], 8}) = 1 (in [0])
세 번째 터미널에서는 두 번째 셸(추적 중인 셸의 부모)을 종료합니다.
$ kill -9 41934
그러다가 나는 관찰했다.아무것도 없다strace
출력 에서 세 번째 셸은 여전히 실행 중입니다.
이제 첫 번째 터미널에 무언가를 입력하려고 하면 출력에 다음이 표시됩니다 strace
.
read(0, 0x7ffd6879ebbf, 1) = -1 EIO (Input/output error)
...
write(2, "exit\n", 5) = 5
...
setpgid(0, 41938) = 0
exit_group(0) = ?
세 번째 셸은 read
표준 입력(파일 설명자 0 - 이 경우 첫 번째 인수)에서 데이터를 읽는 데 실패하고 자체적으로 종료됩니다. 상위 프로세스를 종료하면 어떤 방식으로든 터미널 장치의 상태가 변경되어 read()
하위 프로세스가 실패하는 것처럼 보입니다.
실험을 반복하되 이번에는 첫 번째 셸(내가 종료하려는 프로세스의 상위 프로세스)을 추적합니다.
$ echo $$
48134
$ bash
$ echo $$ $PPID
48163 48134
$ bash
$ echo $$ $PPID
48169 48163
별도의 터미널에서 첫 번째 셸을 추적합니다.
$ strace -p 48134
strace: Process 48134 attached
wait4(-1,
다른 터미널에서 두 번째 셸을 종료합니다.
$ kill -9 48163
원래 껍질은 아이의 죽음에 어떻게 반응했습니까?
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGKILL}], WSTOPPED|WCONTINUED, NULL) = 48163
rt_sigprocmask(SIG_BLOCK, [CHLD TSTP TTIN TTOU], [CHLD], 8) = 0
ioctl(255, TIOCSPGRP, [48134]) = 0
ioctl()
매개변수를 사용한 호출에 유의하세요 TIOCSPGRP
. 첫 번째 쉘이 자식 프로세스가 종료되었음을 알아차리면 터미널의 전경 프로세스 그룹 ID를 다시 자신으로 변경합니다(fd 255는 터미널 장치의 열린 파일 설명자이기도 함). 이것이 read()
세 번째 셸이 실패하는 원인입니다. 장치에서 읽으려고 시도하지만 포그라운드 프로세스 그룹에 있지 않습니다.