中断组合键(例如 CTRL-C)如何以及何时转换为信号?

How and when are interrupt key combination,such as CTRL-C, translated to signals?

使用 Linux OS,我需要透明地将所有击键从远程连接传递到本地硬件连接。这对于除信号之外的所有内容都是相当直接的。我知道我可以为捕获和传递击键的每个信号注册处理程序,但这似乎是一种黑客攻击,可能不适用于边缘情况(如果有人更改中断键组合映射怎么办,我会两次传递击键,等等。 ).

为了想出一个更好的解决方案,我真的需要更多地了解按键组合,IE:CTRL-C,如何变成信号,IE:SIGINT。

  1. 组合键如何成为信号(在内核、客户端应用程序、运行时)?
  2. 击键还通过吗?如果 CTRL-C 有一个空处理程序,STDIN 是否仍然得到 CTRL-C?
  3. 不将任何击键解释为信号组合的最佳方法是什么?这可以在 TTY 或环境设置中完成吗?
  1. 终端的线路规程将按键组合转换为信号,这是 TTY 子系统中的一个层。这是描述 from Wikipedia:

For example, the standard line discipline processes the data it receives from the hardware driver and from applications writing to the device according to the requirements of a terminal on a Unix-like system. On input, it handles special characters such as the interrupt character (typically Control-C) and the erase and kill characters (typically backspace or delete, and Control-U, respectively) and, on output, it replaces all the LF characters with a CR/LF sequence.

  1. 按键未通过,发出信号时被抑制。如果进程没有 SIGINT 处理程序,内核将终止它。

  2. 您显然可以覆盖它:这就是像 ssh 这样的工具的工作方式。您可以通过将终端设置为 "raw" 模式轻松地做到这一点,例如使用 shell 命令 stty raw。如果你然后 运行 cat -vE 你可以按你想要的任何键并看到它们以脱字符号打印。确保计划好关闭终端的方法,因为你显然不能 Ctrl-C/Z/D 离开它了。

How does the keycombo become a Signal (in the kernel, client application, runtime)?

此翻译是作为 the kernel's TTY line discipline 的一部分执行的。作为此过程的一部分,还执行了许多其他翻译,例如 end-of-file (^D)、停止信号 (^Z)、字符回显、基本行编辑(退格键、^U 等)和 DEL/BS 和 CR/CRLF 翻译。

Is the keystroke still passed? If CTRL-C has a null handler, does STDIN still get CTRL-C?

没有。由行规程处理的控制字符不会传递到前台进程。

What is the best way to not interpret any keystroke as a signal combination? Can this be done in TTY or Environment settings?

使用tcgetattr() and tcsetattr()更改终端属性。 struct termiosc_cc 元素包含控制字符的设置;您可以通过将它们设置为 _POSIX_VDISABLE.

来禁用部分或全部元素

(您也可以使用 cfmakeraw()——记录在上面的同一页——来清除 struct termios 的大部分元素,给你一个主要是 "raw" 的终端。但是,这可能会禁用比您预期更多的终端行为。)