Shell

為什麼 SIGINT 在發送到其父程序時不會傳播到子程序?

  • February 3, 2020

給定一個 shell 程序(例如sh)及其子程序(例如cat),我如何使用 shell 的程序 ID模擬Ctrl+的行為?C


這是我嘗試過的:

執行sh然後cat

[user@host ~]$ sh
sh-4.3$ cat
test
test

從另一個終端發送SIGINT到:cat

[user@host ~]$ kill -SIGINT $PID_OF_CAT

cat收到信號並終止(如預期)。

將信號發送到父程序似乎不起作用。為什麼信號cat在發送到其父程序時沒有傳播到sh

這不起作用:

[user@host ~]$ kill -SIGINT $PID_OF_SH

CTRL+如何C工作

首先是了解CTRL+是如何C工作的。

當您按CTRL+C時,您的終端仿真器會發送一個 ETX 字元(文本結尾/0x03)。

TTY 被配置為當它接收到這個字元時,它會向終端的前台程序組發送一個 SIGINT。這個配置可以通過doingstty -a和looking來查看intr = ^C;POSIX 規範說,當收到 INTR 時,它應該向該終端的前台程序組發送一個 SIGINT。

什麼是前台程序組?

那麼,現在的問題是,如何確定前台程序組是什麼?前台程序組只是將接收鍵盤生成的任何信號(SIGTSTP、SIGINT 等)的程序組。

確定程序組 ID 的最簡單方法是使用ps

ps ax -O tpgid

第二列將是程序組 ID。

如何向程序組發送信號?

現在我們知道程序組 ID 是什麼,我們需要模擬向整個組發送信號的 POSIX 行為。

這可以通過在組 ID 前面kill放置一個來完成。 例如,如果您的程序組 ID 是 1234,您將使用:-

kill -INT -1234

使用終端號模擬CTRL+ 。C

因此,以上內容涵蓋瞭如何將CTRL+模擬C為手動過程。但是,如果您知道 TTY 號碼,並且想為該終端模擬CTRL+怎麼辦?C

這變得非常容易。

假設$tty是您要定位的終端(您可以通過tty | sed 's#^/dev/##'在終端中執行來獲得它)。

kill -INT -$(ps h -t $tty -o tpgid | uniq)

這將向前台程序組發送一個 SIGINT $tty

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