당황하지 말 것.

당황하지 말 것.

나는 그것을 사용하고 있다우분투14.04이해할 수 없는 동작이 발생합니다.

  1. 명령을 실행합니다 yes(기본 셸에서:불다)
  2. CtrlZ중지하려면 입력하세요 .yes
  3. 달리기 jobs. 산출:
    [1]+ Stopped yes
  4. kill -9 %1정지할 때까지 달리십시오 yes. 산출:
    [1]+ Stopped yes
  5. 달리기 jobs. 산출:
    [1]+ Stopped yes

이것은 3.16.0-30-generic병렬 가상 머신에서 실행되는 Ubuntu에 있습니다.

kill -9내 명령이 종료되지 않는 이유는 무엇입니까?주문하다? 제 생각에는신호 살해잡히거나 무시할 수 없습니까? 어떻게 종료할 수 있어?주문하다?

답변1

프로세스를 일시 중지하라는 신호가 차단되었습니다. 터미널에서:

$ yes
...
y
y
^Zy

[1]+  Stopped                 yes

두 번째 터미널에서:

$ killall yes

첫 번째 터미널에서:

$ jobs
[1]+  Stopped                 yes

$ fg
yes
Terminated

하지만 SIGKILL멈출 수는 없습니다. 두 번째 터미널에서 동일한 작업을 수행하면 killall -9 yes터미널에서 즉시 결과를 얻을 수 있습니다 yes.

[1]+  Killed                  yes

따라서 kill -9 %1프로세스를 즉시 종료하지 않으면 bash프로세스를 폐기할 때까지 신호가 실제로 전송되지 않거나 fg커널에서 버그를 발견한 것입니다.

답변2

당황하지 말 것.

이상한 일은 일어나지 않습니다. 여기에는 커널 버그가 없습니다. 이는 Bourne Again 쉘 및 멀티태스킹 운영 체제의 완전히 정상적인 동작입니다.

기억해야 할 것은자살을 처리하다, 또는 응답할 수도 있습니다 SIGKILL. 여기서 일어나는 일은 Bourne Again 쉘이 무언가를 처리하고 있다는 것입니다.앞으로단지 자신을 죽이는 과정이 실제로는 자신을 죽였다고 스스로에게 말했을 뿐입니다.

yes중지 지점에서 어떤 일이 발생하는지 고려 SIGTSTP하고 killBourne Again 셸을 사용하여 이 명령을 실행했습니다.

  1. 쉘이 프로세스 SIGKILL로 전송됩니다 .yes
  2. 평행하게:
    1. 프로세스 yes가 실행되고 즉시 종료되도록 예약됩니다.
    2. Bourne Again 쉘이 계속해서 또 다른 프롬프트를 발행합니다.

당신이 한 가지를 보고 다른 사람이 다른 것을 보는 이유는 실행할 준비가 된 두 프로세스 간의 단순한 경쟁 때문입니다. 여기서 승자는 전적으로 기계 간에 그리고 시간이 지남에 따라 변화하는 것에 달려 있습니다. CPU가 가상이라는 사실과 마찬가지로 시스템 로드도 영향을 미칩니다.

흥미로운 경우 2단계의 세부정보는 다음과 같습니다.

  1. Bourne Again 쉘이 계속됩니다.
  2. kill내부적으로 내장된 명령의 일부로 작업 테이블의 항목을 다음과 같이 표시합니다 .알림 메시지를 인쇄해야 합니다.다음 이용 가능한 지점에서.
  3. 명령을 완료 kill하고 프롬프트를 인쇄하기 전에 작업에 대한 알림 메시지를 인쇄해야 하는지 여부를 다시 확인합니다.
  4. 프로세스 yes가 스스로 종료할 기회가 없었으므로 쉘에 관한 한 작업은 여전히 ​​중지됩니다. 따라서 셸은 작업의 "중지됨" 작업 상태 줄을 인쇄하고 해당 알림 보류 플래그를 재설정합니다.
  5. 프로세스 yes가 예약되고 자체적으로 종료됩니다.
  6. 커널은 명령줄 편집기를 실행 중이던 셸에 프로세스가 자체적으로 종료되었음을 알립니다. 셸은 상태 변경을 기록하고 작업을 다시 보류 중인 것으로 표시합니다.
  7. enter루프 프롬프트 print를 다시 누르기만 하면 쉘이 새 작업 상태를 인쇄할 수 있는 기회를 얻을 수 있습니다.

요점은 다음과 같습니다.

  • 프로세스가 자체적으로 종료됩니다. SIGKILL이것은 마법이 아닙니다. 프로세스는 페이지 오류, (비중첩) 인터럽트 및 시스템 호출이 끝날 때 발생하는 커널 모드에서 애플리케이션 모드로 돌아갈 때 보류 중인 신호를 확인합니다. 유일한 특별한 점은 커널이 SIGKILL즉각적이고 무조건적인 자살 이외의 대응 작업을 허용하지 않으며 응용 프로그램 모드로 돌아가지 않는다는 것입니다. 중요한 것은 프로세스가 커널에서 애플리케이션 모드로 전환되어야 한다는 것입니다.그리고신호에 응답하여 실행되도록 예약되었습니다.
  • 가상 CPU는 호스트 운영 체제의 스레드일 뿐입니다. 호스트가 가상 CPU 실행을 예약했다는 보장은 없습니다. 호스트 운영 체제도 마술적이지 않습니다.
  • 작업 상태가 변경되면 알림 메시지가 인쇄되지 않습니다(사용하지 않는 한 set -o notify). 셸이 실행 주기의 다음 지점에 도달하면 인쇄되어 보류 중인 알림이 있는지 확인합니다.
  • 알림 보류 플래그는 신호 처리기 kill에 의해 한 번, 두 번 설정됩니다. SIGCHLD즉 사람들이 볼 수 있다는 뜻이다.yes프로세스가 자체적으로 종료되도록 다시 예약되기 전에 셸이 실행되면 메시지가 나타납니다. 하나는 "중지됨" 메시지이고 다른 하나는 "종료됨" 메시지입니다.
  • 분명히 이 /bin/kill프로그램은 쉘의 내부 작업 테이블에 액세스할 수 없으므로 그러한 동작을 볼 수 없습니다 /bin/kill. 알림 보류 플래그는 핸들러에 의해 한 번만 설정됩니다 SIGCHLD.
  • 같은 이유로 다른 쉘에서 처리하는 경우에는 kill이 동작이 표시되지 않습니다 .yes

답변3

당신이 관찰하고 있는 것은 이 bash 버전의 버그입니다.

kill -9 %1작업은 실제로 즉시 종료됩니다. 를 사용하여 이를 관찰할 수 있습니다 ps. bash 프로세스를 추적하여 시스템 호출이 호출되는 시기를 확인 kill하고 하위 프로세스를 추적하여 신호를 수신하고 처리하는 시기를 확인할 수 있습니다. 더 흥미로운 점은 이 과정에서 무슨 일이 일어나는지 직접 가서 볼 수 있다는 것입니다.

bash-4.3$ sleep 9999
^Z
[1]+  Stopped                 sleep 9999
bash-4.3$ kill -9 %1

[1]+  Stopped                 sleep 9999
bash-4.3$ jobs
[1]+  Stopped                 sleep 9999
bash-4.3$ jobs -l
[1]+  3083 Stopped                 sleep 9999
bash-4.3$ 

다른 터미널에서:

% ps 3083
  PID TTY      STAT   TIME COMMAND
 3083 pts/4    Z      0:00 [sleep] <defunct>

자식 프로세스는좀비. 그것은 죽었습니다. 남은 것은 프로세스 테이블의 항목뿐입니다(그러나 메모리, 코드, 열린 파일 등은 없습니다). 해당 항목은 부모가 통지하고 통과할 때까지 유지됩니다.wait시스템 호출 또는 그 형제 중 하나.

대화형 쉘은 죽은 하위 프로세스를 확인하고 프롬프트를 인쇄하기 전에 이를 캡처해야 합니다(달리 구성하지 않는 한). 이 버전의 bash에서는 다음과 같은 경우에 이를 수행할 수 없습니다.

bash-4.3$ jobs -l
[1]+  3083 Stopped                 sleep 9999
bash-4.3$ true
bash-4.3$ /bin/true
[1]+  Killed                  sleep 9999

명령이 프롬프트를 인쇄한 직후 bash가 "Killed"를 보고할 것으로 예상할 수 있지만 kill경쟁 조건으로 인해 이는 보장되지 않습니다. 신호는 비동기식으로 전달됩니다. kill커널이 신호를 전달할 프로세스를 결정하자마자 시스템 호출은 신호가 실제로 전달될 때까지 기다리지 않고 즉시 반환됩니다. bash는 하위 프로세스의 상태를 확인하고 아직 죽지 않았음을 확인하고( wait4자식 프로세스 종료를 보고하지 않음) 프로세스가 여전히 중지되었음을 인쇄할 시간을 가질 수 있으며 실제로 실제로 발생합니다 . 오류는 다음 프롬프트 전에 신호가 전달되었지만( ps프로세스가 종료되었음을 보고) bash가 여전히 호출되지 않는다는 wait4것입니다(우리가 볼 수 있듯이 이는 여전히 작업이 "중지됨"으로 보고되기 때문일 뿐만 아니라 또한 프로세스 테이블에 좀비가 아직 남아 있기 때문입니다. 실제로 bash는 wait4다음에 호출해야 할 때만 좀비를 가져오고 다른 외부 명령을 실행합니다.

오류는 간헐적으로 발생하며 bash를 추적할 때 이를 재현할 수 없습니다(아마도 bash가 빠르게 반응해야 하는 경쟁 조건이기 때문일 것입니다). bash 검사 전에 신호가 전달되면 모든 것이 예상대로 발생합니다.

답변4

시스템에 뭔가 이상한 일이 벌어지고 있을 수도 있습니다. 내 -9레시피에서는 다음이 있든 없든 잘 작동합니다.

> yes
...
^Z
[1]+  Stopped                 yes
> jobs
[1]+  Stopped                 yes
> kill %1
[1]+  Killed                  yes
> jobs
> 

pid를 얻고 jobs -p그것을 죽이려고 노력하십시오 root.

관련 정보