Process

kill -9 $PPID 殺死程序?

  • October 8, 2020

我讀到殺死父程序將使子程序附加到init(PPID = 1)。

為了測試這一點,我創建了三個 shell 並向第二個發送了終止信號:

# 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和exit都列印到螢幕上,不輸入)

但是第三個 shell 也被殺死了,而不是附加到 init 上。為什麼和由誰?

我將重新創建您的實驗:

# First shell
$ echo $$
41903

# Start the second shell
$ bash
$ echo $$ $PPID
41934 41903

# Start the third shell
$ bash
$ echo $$ $PPID
41938 41934

現在,在第二個終端中,我將使用它strace來監視第三個 shell 執行的系統呼叫和處理的信號。請注意,shell 在等待輸入時被阻塞:

$ strace -p 41938
strace: Process 41938 attached
pselect6(1, [0], NULL, NULL, NULL, {[], 8}) = 1 (in [0])

在第三個終端中,我將殺死第二個 shell(我正在跟踪的那個的父級):

$ kill -9 41934

此時,我在輸出中沒有觀察到任何東西strace——第三個 shell 仍在執行。

現在,如果我嘗試在第一個終端中輸入內容,我會在strace輸出中看到以下內容:

read(0, 0x7ffd6879ebbf, 1)              = -1 EIO (Input/output error)
...
write(2, "exit\n", 5)                   = 5
...
setpgid(0, 41938)                       = 0
exit_group(0)                           = ?

第三個 shell 未能從標準輸入(文件描述符 0——read在這種情況下為第一個參數)讀取並自行終止。殺死父程序似乎以某種方式改變了終端設備的狀態,導致子程序read()失敗。

讓我們重複這個實驗,但這次跟踪第一個 shell——我將要殺死的程序的父程序。

$ echo $$
48134

$ bash
$ echo $$ $PPID
48163 48134

$ bash
$ echo $$ $PPID
48169 48163

在一個單獨的終端中,跟踪第一個 shell:

$ strace -p 48134
strace: Process 48134 attached
wait4(-1, 

在另一個終端中,殺死第二個 shell:

$ 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參數的呼叫。當第一個 shell 注意到它的子程序終止時,它會將終端的前台程序組 ID 改回它自己(注意 fd 255 也是終端設備的打開文件描述符)。這就是導致read()第三個 shell 失敗的原因——它試圖從設備中讀取,但不在前台程序組中。

引用自:https://unix.stackexchange.com/questions/612990