终端里到底有什么 书架

第 07 章 / 共 12 章

第七章 · 假终端 pty

第六章结尾留了个扣子:程序会问内核「我的输出那头是终端吗?」在电传打字机时代这问题很好回答——是就是,不是就不是。可今天根本没有硬件终端,你打开的只是一个 mac 窗口。内核拿什么回答?

答案是:内核伪造了一台终端。这个伪造品叫假终端(pseudo-terminal,简称 pty),它是全书最关键的一块积木——SSH、tmux、expect、script 录制命令行,全站在它上面。

一对孪生的门

pty 的构造很朴素:内核里开一对连在一起的「字符设备」,像一扇门的两面:

两面之间的规则对称得漂亮:写进主面的字节,能从从面读出来;写进从面的字节,能从主面读出来。就像那根串口线,只不过两端都是程序。

于是整个结构一目了然:iTerm2 拿着主面,假装自己是一台 VT100;shell 拿着从面,真心实意地以为自己连着一台真终端。shell 调用 isatty,内核看了看——是 pty 的从面——回答「是」。谎言天衣无缝。

一个实验就能看见这扇门:开两个终端窗口。窗口 A 敲 tty,得到比如 /dev/ttys003;窗口 B 敲 echo hello > /dev/ttys003——hello 出现在窗口 A 的屏幕上游荡。你刚刚徒手把字节写进了别人终端的「从面」,被 A 的模拟器画了出来。

pty 不只是根管子,它还带着「打字机行为」

注意 pty 和第六章的管道不是一回事。管道是纯字节通道;pty 的从面还附赠一整套第一章以来讲的打字机行为——回显、行缓冲、把 Ctrl-C 翻译成信号(第十章)、记录窗口大小。这些行为由内核里 pty 自带的一层代码(就是第二章说的 tty 层,规范模式/原始模式那些设置)提供。

这就是为什么「管道不够用」:如果 iTerm2 只用普通管道连 shell,shell 一 isatty 发现对面不是终端,行编辑、颜色、Ctrl-C 全都没有了——你会得到一个残废的命令行。pty 存在的全部意义,就是让「假装是终端」这件事连行为细节都像。

谁都能开一对:pty 是公共积木

一旦明白 pty 是「任何程序都能向内核申请的一对门」,一堆工具立刻褪掉神秘色彩:

还有个日常痕迹:每个 pty 从面都是 /dev/ 下的一个文件(mac 上 ttys00X,Linux 上 pts/N),你开几个终端窗口/tmux 窗格就有几个。who 命令列出来的那一列,就是这些文件名。

为什么要绕这么大一圈?

值得停下来问一句:图形界面时代,为什么还要让内核费事伪造打字机?直接让 shell 跟 iTerm2 用一种新协议说话不行吗?

不行,而且原因深刻:pty 让四十年来所有为「真终端」写的程序无需修改就能跑在图形界面里。vim、less、你的 shell、以及 1980 年代编译出来的老古董,它们只认「终端」这个抽象。内核把抽象保留下来、把硬件抽掉,新老世界就接上了。这是 Unix 最典型的生存策略:抽象不动,实现偷换。

一句话总结:pty 是内核提供的一对「门」,主面给冒充终端的程序,从面给使用终端的程序,中间还附赠回显、行缓冲、信号翻译等全套打字机行为。图形界面的一切终端体验,都建立在这个美丽的谎言上。

现在,把「冒充终端的程序」从你的电脑搬到千里之外:主面不再连本地窗口,而是连一根网线。这就是 SSH——下一章。

终端里到底有什么
费曼式写法 · 由多个 AI 代理撰写与互相审校