键盘输入和文本输出如何工作?

键盘输入和文本输出如何工作?

假设我A在文本编辑器中按下该键,这会将字符插入a到文档中并将其显示在屏幕上。我知道编辑器应用程序不直接与硬件通信(中间有内核和其他东西),那么我的计算机内部发生了什么?

答案1

有几种不同的场景;我将描述最常见的。连续的宏观事件是:

  1. 输入:按键事件从键盘硬件传输到应用程序。
  2. 处理:应用程序决定因为A按下了该键,所以必须显示字符a
  3. a输出:应用程序给出在屏幕上显示的命令。

图形用户界面应用程序

UNIX 系统事实上的标准图形用户界面是X窗口系统,通常称为 X11,因为它在应用程序和显示服务器之间的核心协议的第 11 版中稳定下来。一个称为 X 服务器的程序位于操作系统内核和应用程序之间;它提供的服务包括在屏幕上显示窗口以及将按键传输到具有焦点的窗口。

输入

+----------+              +-------------+         +-----+
| keyboard |------------->| motherboard |-------->| CPU |
+----------+              +-------------+         +-----+
             USB, PS/2, …                 PCI, …
             key down/up

首先,有关按键按下和按键释放的信息从键盘传输到计算机以及计算机内部。详细信息取决于硬件类型。我不会详细讨论这一部分,因为整个链的这一部分中的信息保持不变:按下或释放了某个键。

         +--------+        +----------+          +-------------+
-------->| kernel |------->| X server |--------->| application |
         +--------+        +----------+          +-------------+
interrupt          scancode             keysym
                   =keycode            +modifiers

当硬件事件发生时,CPU会触发打断,这会导致一些代码核心执行。此代码检测硬件事件是来自键盘的按键按下或按键释放,并记录扫码它标识了密钥。

X服务器通过a读取输入事件设备文件,例如/dev/input/eventNNN在 Linux 上(其中 NNN 是数字)。每当有事件发生时,内核都会发出信号,表明有数据可以从该设备读取。设备文件使用扫描码传输按键向上/向下事件,该扫描码可能与硬件传输的值相同也可能不同(内核可能会将扫描码从键盘相关的值转换为通用值,Linux不重传它不知道的扫描码)。

X 调用它读取的扫描码关键代码。 X 服务器维护一个表,将按键代码转换为按键符号(“关键符号”的缩写)。键码是数字,而键符号是名称,例如A, aacute, F1, KP_Add, Control_L, … 键符号可能会有所不同,具体取决于按下的修饰键 ( Shift, Ctrl, …)。

有两种机制可以配置从键码到键符号的映射:

  • xmodmap是传统的机制。它是一个简单的表,将键码映射到键符号列表(未修改、移位等)。
  • XKB是一种更强大但更复杂的机制,可以更好地支持更多修饰符,特别是双语言配置等。

应用程序连接到 X 服务器,并在该应用程序的窗口具有焦点时按下某个键时收到通知。该通知指示按下或释放了某个键符号以及当前按下了哪些修饰符。运行程序就可以看到按键符号xev从终端。应用程序如何处理这些信息取决于它;某些应用程序具有可配置的键绑定。

在典型配置中,当您按下没有修饰符标记的键时A,会将键符号发送a到应用程序;如果应用程序处于键入文本的模式,则会插入字符a

键盘布局与xmodmap的关系更详细地介绍键盘输入。Linux 中的鼠标事件如何工作?概述了较低级别的鼠标输入。

输出

+-------------+        +----------+          +-----+         +---------+
| application |------->| X server |---····-->| GPU |-------->| monitor |
+-------------+        +----------+          +-----+         +---------+
               text or              varies          VGA, DVI,
               image                                HDMI, …

有两种显示字符的方法。

不同类型的 XWindows 字体的用途是什么?有关 X11 下客户端和服务器端文本渲染的讨论。

X 服务器和 X 服务器之间会发生什么图形处理单元(显卡上的处理器)非常依赖硬件。简单的系统让 X 服务器在一个称为 a 的内存区域中绘制帧缓冲区,GPU 拾取并显示。任何 21 世纪 PC 或智能手机上的先进系统允许 GPU 直接执行一些操作以获得更好的性能。最终,GPU 每隔一秒就将屏幕内容逐个像素传输到显示器。

文本模式应用程序,在终端中运行

如果您的文本编辑器是在终端中运行的文本模式应用程序,那么该终端就是用于上一节目的的应用程序。在本节中,我将解释文本模式应用程序和终端之间的接口。首先我描述一个案例终端仿真器在X11下运行。“终端”、“shell”、“tty”和“控制台”之间的确切区别是什么?这里可能是有用的背景。读完本文后,您可能想阅读更详细的内容每个伪终端 (PTY) 组件(软件、主机端、从机端)的职责是什么?

输入

      +-------------------+               +-------------+
----->| terminal emulator |-------------->| application |
      +-------------------+               +-------------+
keysym                     character or
                           escape sequence

终端模拟器接收诸如“Left按下时Shift按下”之类的事件。终端仿真器和文本模式应用程序之间的接口是伪终端 (pty), A字符设备它传输字节。当终端仿真器接收到按键事件时,它会将其转换为应用程序从 pty 设备读取的一个或多个字节。

ASCII 范围之外的可打印字符将作为一个或多个字节进行传输,具体取决于字符和编码。例如,在UTF-8的编码统一码字符集,字符集ASCII码范围被编码为单个字节,而该范围之外的字符被编码为多个字节。

Ctrl对应于功能键或带有修饰符(例如或 )的可打印字符的按键Alt作为转义序列。转义序列通常由字符组成逃脱(字节值 27 = 0x1B = \033,有时表示为^[\e)后跟一个或多个可打印字符。一些按键或按键组合具有控制字符与基于 ASCII 的编码相对应(这几乎是当今使用的所有编码,包括 Unicode):Ctrl+letter产生 1-26 范围内的字符值,是上面看到的转义字符,也与+Esc相同,与+相同,与+相同,等等。Ctrl[TabCtrlIReturnCtrlM

不同的终端针对给定的键或键组合发送不同的转义序列。幸运的是,反之亦然:给定一个序列,实际上最多有一个它编码的按键组合。一个例外是字符 127 = 0x7f =,\0177它经常出现Backspace,但有时也出现Delete

在终端中,如果键入Ctrl+V后跟组合键,则会按字面意思插入组合键中转义序列的第一个字节。由于转义序列通常仅包含第一个字符之后的可打印字符,因此这会按字面插入整个转义序列。看键绑定表?在此背景下讨论 zsh。

终端可以为某些修饰符组合传输相同的转义序列(例如,许多终端为 和Space+Shift传输空格字符Spacexterm 有一个模式来区分修饰符组合基于流行的 vte 库的终端不会)。一些键根本不被传输,例如修改键或触发终端仿真器绑定的键(例如复制或粘贴命令)。

如果需要,应用程序可以将转义序列转换为符号键名称。

输出

+-------------+               +-------------------+
| application |-------------->| terminal emulator |--->
+-------------+               +-------------------+
               character or
               escape sequence

输出比输入简单得多。如果应用程序向 pty 设备文件输出一个字符,终端仿真器将在当前光标位置显示该字符。 (终端仿真器维护光标位置,如果光标落在屏幕底部下方,则滚动。)应用程序还可以输出转义序列(大多以^[或开头^])来告诉终端执行诸如移动光标之类的操作,更改文本属性(颜色、粗体等),或擦除屏幕的一部分。

终端仿真器支持的转义序列在术语帽或者术语信息数据库。如今大多数终端仿真器都与xterm。看有关 LESS_TERMCAP_* 变量的文档?对终端能力信息数据库进行更长时间的讨论,以及如何让光标停止闪烁我可以将本地计算机的终端颜色设置为使用我通过 ssh 进入的计算机的终端颜色吗?一些使用示例。

在文本控制台中运行的应用程序

如果应用程序直接在文本控制台(即由内核而不是终端仿真器应用程序提供的终端)中运行,则适用相同的原理。终端和应用程序之间的接口仍然是传输字符的字节流,具有编码为转义序列的特殊键和命令。

远程应用程序,通过网络访问

远程文本应用程序

如果您在远程计算机上运行程序,例如通过SSH,则网络通信协议在 pty 级别中继数据。

+-------------+           +------+           +-----+           +----------+
| application |<--------->| sshd |<--------->| ssh |<--------->| terminal |
+-------------+           +------+           +-----+           +----------+
               byte stream        byte stream       byte stream
               (char/seq)         over TCP/…        (char/seq)

这大部分是透明的,只是有时远程终端数据库可能不知道本地终端的所有功能。

远程 X11 应用程序

应用程序和服务器之间的通信协议本身就是可以通过网络协议(例如 SSH)发送的字节流。

+-------------+            +------+        +-----+            +----------+
| application |<---------->| sshd |<------>| ssh |<---------->| X server |
+-------------+            +------+        +-----+            +----------+
               X11 protocol        X11 over       X11 protocol
                                   TCP/…

这基本上是透明的,除了一些需要应用程序和显示器之间直接通信的加速功能(例如电影解码和 3D 渲染)不可用。

答案2

如果你想在一个小到可以理解的 Unix 系统中看到这一点,请深入研究Xv6。它或多或少是神话般的 Unix 第六版,它成为 John Lion 著名的基础评论,作为地下出版物长期流传。它的代码经过重新设计,可以在 ANSI C 下编译,并考虑到现代发展,如多处理器。

相关内容