2026-07-21
今日主题
- 终端控制码与输入分层
新增认知
终端控制码与输入分层
-
终端输入是三层堆叠:终端文本输入自下而上分三层——termios 信号/流控层(ISIG/IXON,
处理 Ctrl-C/Z/S/Q)、termios canonical 层(ICANON,
内核 N_TTY 行规程处理 backspace/Ctrl-W/U/D)、readline 等用户态库层(Ctrl-A/E、Ctrl-R 历史、补全)。
三层是历史有机堆叠而非一套设计,由此可解释终端诸多反直觉现象(Ctrl-1 无意义、Ctrl-M=Enter、同键不同程序行为不同)。
判断程序输入能力的关键是先确认它处在哪一层。 -
33 控制码是混杂遗产:终端仅 33 个 ASCII 控制码(Ctrl-A~Z 加 @[]^_? 七个),
来源是电报机遗产+OS 终端驱动+readline 约定+各程序自定义的历史堆叠,无统一结构。直接后果:
Ctrl-1/Ctrl+Shift+C 不是控制码、Ctrl-M 等于 Enter、Ctrl-I 等于 Tab、同码多义冲突(Ctrl-S 既冻结屏幕又可做前向搜索)。
ASCII 官方名字(如 ETX)约半数已与今日 UNIX 行为无关,可忽略。 -
canonical 是 readline 穷人版:
termios 的 ICANON(cooked/canonical mode)是内核 N_TTY 行规程的极简行编辑,
仅认 ERASE、KILL(Ctrl-U)、WERASE(Ctrl-W)、EOF(Ctrl-D)、LNEXT(Ctrl-V)、REPRINT(Ctrl-R),
对应 cat/nc/git 等 baseline 程序免费获得的能力。但无行首尾跳转、按词移动、历史、Ctrl-R 反向搜索、补全——
这些是 readline(独立 GPL 用户态库)独有,与 termios 不在同一层。 -
readline 工作时关掉 ICANON:反直觉证据证明 canonical≠readline:readline 要每个按键立刻送达,
故切到 noncanonical 模式(cfmakeraw 清掉 ICANON|ISIG|ECHO|IEXTEN),自己接管按键解释与回显。
vim/less 等全屏 TUI 同理。若 termios 真自带 readline 模式,readline 就不必自己关 ICANON、逐字节读取了。 -
同键在两层行为不同:Ctrl-W/Ctrl-U 在 baseline 程序(cat/git,
ICANON 开)由内核 termios 的 VWERASE/VKILL 处理;在 readline 程序(bash/python3,
ICANON 关)由 readline 库自处理。行为还有细微差别:readline 的 Ctrl-U 是删到行首而非删整行,Ctrl-W 对词的定义不同——
证明是两套独立实现而非同一物。判断程序用哪层:按 Ctrl-R 出现 reverse-i-search 即 readline,
方向键吐 ^[[D 即 baseline。