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

dar*_*ine 5 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发送到该会话的当前前台进程组,该进程组仅包括我们管道中的进程.

我的问题是,到目前为止我的理解是否正确,xterm如何告诉内核将SIGINT发送到给定控制终端的会话?

dar*_*ine 13

tl;dr 内核做到了。

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

每当将 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 并让您挂起。