详细说明,在终端中按Ctrl-C会发生什么?

时间:2017-09-01 04:48:21

标签: bash shell session signals

详细说明,在终端中按Ctrl-C会发生什么?是的,我知道它发送了SIGINT,但是到达那里需要采取哪些步骤?

我做了一些研究,所以我想我理解了大部分的图片,但不是全部。

为了教学,我假设我们在X会话中运行终端模拟器xterm。终端正在运行Bash shell,而shell当前正在运行一些长时间运行的管道,该管道由前台的多个进程组成。

  1. 我按下键盘上的Ctrl-C。
  2. X将键盘事件发送到xterm。
  3. xterm翻译Ctrl-C键盘事件并将其发送到它所持有的伪tty主文件描述符? (有些神奇的事情发生了)
  4. 内核检测到伪tty上发生了一些特殊的SIGINT事件,并找到控制终端为此tty的会话。它将SIGINT发送到该会话的当前前台进程组,该进程组仅包括我们管道中的进程。
  5. 我的问题是,到目前为止我的理解是否正确,xterm如何告诉内核将SIGINT发送到给定控制终端的会话?

1 个答案:

答案 0 :(得分:2)

tl;内核是否做到了。

每个pty(伪tty)有两个端点,一个是主服务器和一个从服务器。在xterm示例中,xterm将保留在主文件描述符上。任何按键都直接写入主fd。 slave fd(pts或pty slave)由会话拥有并传递给前台进程组。

每当将ASCII ETX字符(^ C)写入主服务器时,内核会将其转换为使用相应的控制终端将SIGINT发送到前台进程组。这实际上是一个pty设置。您可以运行stty -a并查看默认值为intr = ^C;,意味着^C或ETX是" SIGINT"字符。这可以更改为其他角色或完全禁用。

更复杂的例子是Ctrl-C如何通过交互式SSH会话工作。交互式SSH会话在服务器端分配pty。客户端pty设置为原始模式,这意味着客户端内核不会将ETX转换为SIGINT。相反,客户端内核将ETX传递给从属服务器。在这种情况下,ssh客户端进程获取该ETX并将其传递给服务器sshd进程。如果服务器sshd pty不处于原始模式,则服务器的内核会将该ETX转换为其前台进程组的SIGINT。这就是Ctrl-C将SIGINT发送到服务器上运行的进程的方式,而不是杀死客户端SSH并让你挂起。