왜 좀비가 아이를 기다리고 있습니까?


11

나는 다른 출처를 파고 있지만 아이 수확의 해부학에 대한 좋은 설명을 찾을 수 없습니다. 이것은 내가 이해하고 싶은 간단한 사례입니다.

$ cat <( sleep 100 & wait ) &
[1] 14247
$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 S pts/17   00:00:00 bash
14249 12126 S pts/17   00:00:00 sleep 100
14251 14250 S pts/17   00:00:00 grep --color=auto 12126
$ kill -2 14248

$ ps ax -O pgid | grep $$
12126 12126 S pts/17   00:00:00 bash
14248 12126 Z pts/17   00:00:00 [bash] <defunct>
14249 12126 S pts/17   00:00:00 sleep 100
14255 14254 S pts/17   00:00:00 grep --color=auto 12126

왜 좀비가 아이를 기다리고 있습니까?

이것을 설명 할 수 있습니까? 이것에 대한 이해를 넓히려면 C를 알고 Bash 소스 코드를 읽어야합니까? 아니면 문서가 있습니까? 나는 이미 상담했다 :

GNU bash, 버전 4.3.42 (1)-릴리스 (x86_64-pc-linux-gnu)

Linux 4.4.0-31-generic # 50-Ubuntu SMP 수요일 7 월 13 일 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU / Linux


2
이것은 bash와 실제로는 아무런 관련이 없습니다 (bash로 bash를 사용하기로 선택한 경우 많은 프로세스가 시작됩니다). 다른 쉘 (tcsh, ksh, zsh, & c)은 모두 프로세스를 시작하고 본질적으로 동일한 OS 기능을 실행하여 처리합니다.
jamesqf

@jamesqf 재미있는. 귀하의 의견을 본격적인 답변으로 확장하고 싶다면, 그것은 좋을 것입니다.

1
그것이 실제로 답이 아니라는 것을 제외하고, 당신이 잘못된 곳에서 답을 찾고 있다고 지적하면 :-) * nix 시스템 프로그래밍에 대한 좋은 책은 내가 쓸 수있는 것보다 훨씬 더 나은 대답을 제공해야합니다.
jamesqf

답변:


17

좀비는 아이를 기다리지 않습니다. 다른 좀비 프로세스와 마찬가지로 부모가 수집 할 때까지 유지됩니다.

무슨 일이 일어나고 있는지 이해하기 위해 관련된 모든 프로세스를 표시하고 PPID도 살펴 봐야합니다. 이 명령 행을 사용하십시오.

ps -t $(tty) -O ppid,pgid

죽이는 프로세스의 부모는 cat입니다. bash는 cat <( sleep 100 & wait )서브 쉘에서 백그라운드 명령 을 실행합니다 . 이 서브 쉘이 수행하는 유일한 작업은 일부 리디렉션을 설정 한 다음 외부 명령을 실행하는 것이므로이 서브 쉘은 외부 명령으로 대체됩니다. 요약은 다음과 같습니다.

  • 원래 bash (12126) 는 자식 ( 14247) fork에서 백그라운드 명령을 실행하기 위해 호출 합니다 cat <( sleep 100 & wait ).
    • 자식 (14247) pipe은 파이프 fork를 생성 한 다음 프로세스 대체를 실행할 자식을 생성하도록 호출 합니다 sleep 100 & wait.
      • 손자 (14248) 는 백그라운드에서 fork실행되도록 호출 합니다 sleep 100. 손자는 대화식이 아니기 때문에 백그라운드 프로세스는 별도의 프로세스 그룹에서 실행되지 않습니다. 그런 다음 손자는 sleep나올 때까지 기다립니다 .
    • 자식 (14247)은 setpgid(대화식 쉘의 백그라운드 작업이므로 자체 프로세스 그룹을 가져옵니다 ) 호출 한 다음 execve실행 cat합니다. (백그라운드 프로세스 그룹에서 프로세스 대체가 일어나지 않는다는 것에 약간 놀랐습니다.)
  • 손자를 죽입니다 (14248). 부모가 실행 cat중이므로 자식 프로세스에 대해 아무것도 모르고 비즈니스 전화를 걸지 않습니다 wait. 손자의 부모는 그것을 거두지 않기 때문에 손자는 좀비로 남아 있습니다.
  • 결국, cat종료 – sleep파이프 를 죽이거나 파이프를 리턴하고 닫아서 cat입력의 끝을 볼 수 있기 때문에 종료됩니다 . 이 시점에서 좀비의 부모가 죽으므로 좀비는 init에 의해 수집되고 초기화됩니다.

명령을 다음으로 변경하면

{ cat <( sleep 100 & wait ); echo done; } &

그런 다음 cat원래 bash 프로세스의 하위가 아닌 별도의 프로세스에서 실행 echo done됩니다. 첫 번째 하위는 실행하기 위해 남아 있어야합니다 . 이 경우 손자를 죽이면 좀비로 남아 있지 않습니다. 그 시점에서 여전히 bash를 실행하는 자식이 그것을 가져 오기 때문입니다.

참조 리눅스 핸들이 과정 좀비 않는 방법좀비가 고아를 가질 수 있습니까? 고아 아이들이 좀비를 거두어 방해받을 수 있습니까?


프로세스 그룹도 놀랐습니다. 버그 인 것처럼 보이며 이제 bash 마스터 브랜치에서 수정되었습니다.
PSkocik

"원래의 bash는 자식을 기다립니다 (14247)." 왜 또는 어떤 방법으로? 아이는 백그라운드에서 실행되어야하며 명시적인 호출이 없습니다. 14247을 기다리는 원래 bash (14246)와 14247을 cat기다리는 14247 (대기 중 sleep) 사이의 차이점은 무엇입니까 ? 아이 (14247)가 잃어버린 오리지널 배쉬 (14246)가 누구를 기다리지 않았는지, 또는 누가 호출해야하는지 SIGCHLD와 같은 신호 목록과 14246 (현재 실행 중 bash)의 구독 취소에 대한 기억이 있습니까? 14248에 관해서?

1
@tomas 나는 원래 bash가 wait자식을 호출한다는 것을 의미했다 . 나는 이것이 어떻게 혼란 스러울 수 있는지 알 수 있으며, 올바른 시점 에서조차도 말로 표현되지 않은 문장을 제거했습니다. 프로세스가 종료 된 정보는 해당 프로세스의 상위 프로세스로 이동하며 프로세스는 다른 프로세스의 사망에 대한 정보를 수신하기 위해 "구독"할 수 없습니다.
Gilles 'SO- 악 그만

6

좀비는 아이를 기다리지 않습니다. 대신, 좀비는 이미 죽었거나 (예제와 같이 살해 당했음), 코드, 데이터 및 스택 할당이 해제 프로세스이며 이제 종료 코드 만 포함되어 부모가 호출 wait(2)하기 를 기다 립니다. (따라서 마지막으로 프로세스 테이블에서 프로세스 항목을 완전히 정리하십시오)

귀하의 예에서 수면이 끝나면 (또는 사망) 부모는 종료 상태를 읽고 좀비를 수확합니다. 자세한 내용은 위에서 언급 한 내용을 참조 wait(2)하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.