如果我理解吉尔斯的回答是什么原因导致发送各种信号?正确的是,有几个与终端中运行的 shell 进程的作业控制相关的信号:
按键通知:SIGINT、SIGQUIT、SIGTSTP
SIGSTOP、SIGCHLD、SIGCONT、
SIGTTIN 和 SIGTTOU
SIGWINCH 和 SIGHUP。
我想知道哪些终端相关信号是直接发送到shell的子进程而不先到达终端中的shell进程,哪些是先发送到终端中的shell进程并让shell重新发送到其子进程?
例如,对于最常用的两个信号,以下正确吗?
SIGHUP 首先发送到 shell 进程,然后将其重新发送到 shell 的所有子进程,无论它们是在前台还是后台(即何时nohup
可以产生区别)。
当按 Ctrl-C 时,哪一项对于 SIGINT 是正确的:
终端驱动程序仅向前台组中的进程发送 SIGINT,而不向终端中运行的父 shell 进程发送 SIGINT。因此父 shell 进程永远不需要处理 SIGINT。
终端驱动程序将 SIGINT 发送到终端中运行的 shell 进程,shell 进程通过向前台组中的进程重新发送 SIGINT 来处理 SIGINT。
如果我理解 Stéphane Chazelas 的回复https://unix.stackexchange.com/a/384702/674正确,第一个正确吗?
谢谢!
答案1
当您在交互式 shell 中的前台运行作业时,只有该作业中的进程(相应的进程组中)才会收到 SIGINT(由内核而不是 shell 发送)^C
。
当不运行任何前台作业时,即在提示符下,当 shell 等待您输入命令行时,shell 位于前台。因此按^C
then 会向 shell 发送一个 SIGINT 信号,shell 通常将其视为取消当前输入的文本;它还可以终止作为键或完成小部件的一部分调用的命令。您还可以在那里添加您自己的处理程序。
笔记
1 如果 shell 作为脚本的一部分启动,同时还并行运行一些其他命令,则其他进程可能位于同一进程组中。交互式 shell 将尝试在启动时为自己创建一个新的进程组(并使其成为前台进程组),但如果它们的进程已经是进程组领导者,则可能无法这样做。如果你这样做:
bash -c ': <(sleep 1000); exec bash'
然后Ctrl+C按该 shell 的提示bash
,您会发现它sleep
也会被杀死。
sleep
像这样运行时你不会观察到它:
sh -c 'sleep 1000 & exec bash'
在这种情况下,sh
显式忽略异步命令的 SIGINT sleep
(在执行之前将 SIGINT 处置设置为 SIGIGN sleep
)。