

理解 Linux 终端、终端模拟器和伪终端
source link: https://www.techug.com/post/understand-linux-terminal-terminal-simulator-and-pseudo-terminal.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

理解 Linux 终端、终端模拟器和伪终端
你可能听说过 TTY 和 PTY 这些缩写,也在 /dev
目录下看到过 /dev/tty[n]
设备,大概知道它们和 Linux 终端的概念有关。可是你清楚 TTY
、PTY
具体指的是什么,它们有什么区别,以及它们和 shell
又是什么关系呢?为了理解这些,我们需要先回顾一下历史。
在计算机诞生之前,人们发明了 Teleprinter(电传打字机),通过长长的电线点对点连接,发送和接收打印的信息,用于远距离传输电报信息。
在今天你很难想象程序的运行结果需要等到打印出来才能看到,Teleprinter
设备已经进了计算机博物馆。现在我们用 TTY 代表计算机终端(terminal),只是沿用了历史习惯,电传打字机(teletypewriter)曾经是计算机的终端,它的缩写便是 TTY(TeleTYpewriter)。
为了把不同型号的电传打字机接入计算机,需要在操作系统内核安装驱动,为上层应用屏蔽所有的低层细节。
上图是一个典型的 Linux 桌面系统。终端模拟器就像过去的物理终端一样,它监听来自键盘的事件将其发送到 TTY 驱动,并从 TTY 驱动读取响应,通过显卡驱动将结果渲染到显示器上。TTY 驱动 和 line discipline 的行为与原先一样,但不再有 UART 和 物理终端参与。
如何看到一个终端模拟器呢?在 Ubuntu 20
桌面系统上,按 Ctrl+Alt+F3
就会得到一个由内核模拟的 TTY。Linux 上这种模拟的文本终端也被称为虚拟终端(Virtual consoles)。每个虚拟终端都由一个特殊的设备文件 /dev/tty[n]
所表示,与这个虚拟终端的交互,是通过对这个设备文件的读写操作,以及使用ioctl
系统调用操作这个设备文件进行的。通过执行 tty
命令可以查看代表当前虚拟终端的设备文件:
$ tty /dev/tty3
可以看到,当前终端的设备文件是 /dev/tty3
,也就是通过 Ctrl+Alt+F3
得到的虚拟终端。
你可以通过 Ctrl+Alt+F3
到 Ctrl+Alt+F6
在几个虚拟终端之间切换。按 Ctrl+Alt+F2
回到桌面环境。X 系统也是运行在一个终端模拟器上,在 Ubuntu 20
上它对应的设备是 /dev/tty2
,这也是为什么使用 Ctrl+Alt+F2
可以切换到 X 系统的原因。
我们可以看看 X 系统打开的文件中是否包含了设备文件 /dev/tty2
。先查找 X 系统的 PID:
# ps aux | grep Xorg mazhen 1404 0.1 0.6 741884 49996 tty2 Sl+ 08:07 0:13 /usr/lib/xorg/Xorg vt2 -displayfd 3 -auth /run/user/1000/gdm/Xauthority -background none -noreset -keeptty -verbose 3
再看看这个进程(1404)打开了哪些文件:
# ll /proc/1404/fd 总用量 0 dr-x------ 2 mazhen mazhen 0 7月 10 08:07 ./ dr-xr-xr-x 9 mazhen mazhen 0 7月 10 08:07 ../ lrwx------ 1 mazhen mazhen 64 7月 10 08:07 0 -> /dev/tty2 lrwx------ 1 mazhen mazhen 64 7月 10 08:07 1 -> 'socket:[39965]' lrwx------ 1 mazhen mazhen 64 7月 10 10:09 10 -> 'socket:[34615]' ...
可以看到,X 系统确实打开了 /dev/tty2
。
再做一个有趣的实验,在 tty3 下以 root 用户身份执行 echo 命令:
# echo "hello from tty3" > /dev/tty4
再按 Ctrl+Alt+F4
切换到 tty4,能看到从 tty3 发送来的信息。
伪终端(pseudo terminal, PTY)
终端模拟器(terminal emulator) 是运行在内核的模块,我们也可以让终端模拟程序运行在用户区。运行在用户区的终端模拟程序,就被称为伪终端(pseudo terminal, PTY)。
PTY 运行在用户区,更加安全和灵活,同时仍然保留了 TTY 驱动和 line discipline 的功能。常用的伪终端有 xterm,gnome-terminal,以及远程终端 ssh。我们以 Ubuntu 桌面版提供的 gnome-terminal 为例,介绍伪终端如何与 TTY 驱动交互。
我们简单梳理一下远程终端是如何执行命令的。
-
用户在客户端的 terminal 中输入 ssh 命令,经过
PTY master
、TTY 驱动,到达PTY slave
。bash 的标准输入已经设置为了PTY slave
,它从标准输入读取字符序列并解释执行,发现需要启动 ssh 客户端,并请求和远程服务器建 TCP 连接。 -
服务器端接收客户端的 TCP 连接请求,向内核申请创建 PTY,获得一对设备文件描述符。让
ssh server
持有PTY master
,ssh server
fork 出的子进程 bash 持有PTY slave
。bash 的标准输入、标准输出和标准错误都设置为了PTY slave
。 -
当用户在客户端的 terminal 中输入命令
ls -l
和回车键,这些字符经过PTY master
到达 TTY 驱动。我们需要禁用客户端 line discipline 的所有规则,也就是说客户端的 line discipline 不会对特殊字符回车键做处理,而是让命令ls -l
和回车键一起到达PTY slave
。ssh client
从PTY slave
读取字符序列,通过网络,发送给ssh server
。 -
ssh server
将从 TCP 连接上接收到的字节写入PTY master
。TTY 驱动对字节进行缓冲,直到收到特殊字符回车键。 -
由于服务器端的 line discipline 没有禁用
echo
规则,所以 TTY 驱动还会将收到的字符写回PTY master
,ssh server
从PTY master
读取字符,将这些字符通过 TCP 连接发回客户端。注意,这是发回的字符不是ls -l
命令的执行结果,而是ls -l
本身的回显,让客户端能看到自己的输入。 -
在服务器端 TTY 驱动将字符序列传送给
PTY slave
,bash 从PTY slave
读取字符,解释并执行命令ls -l
。bash fork 出ls
子进程,该子进程的标准输入、标准输出和标准错误同样设置为了PTY slave
。ls -l
命令的执行结果写入标准输出PTY slave
,然后执行结果通过 TTY 驱动到达PTY master
,再由ssh server
通过 TCP 连接发送给ssh client
。
注意在客户端,我们在屏幕上看到的所有字符都来自于远程服务器。包括我们输入的内容,也是远程服务器上的 line discipline 应用 echo
规则的结果,将这些字符回显了回来。表面看似简单的在远程终端上执行了一条命令,实际上底下确是波涛汹涌。
简单回顾总结一下本文的主要内容:
-
电传打字机(TTY)是物理设备,最初是为电报设计的,后来被连接到计算机上,发送输入和获取输出。
-
电传打字机(TTY)现在被运行在内核中的模块所模拟,被称为终端模拟器(terminal emulator)。
-
伪终端(pseudo terminal, PTY) 是运行在用户区的终端模拟程序。
-
Shell
由terminal
fork 出来,是terminal
的子进程。Shell
不处理键盘事件,也不负责字符的显示,这些是由terminal
处理。Shell
负责解释执行用户输入的字符。 -
可以使用
stty
命令对 TTY 设备进行配置。 -
远程终端
ssh
也是一种伪终端 PTY。
相信通过这篇文章,你已经能够理解终端、终端模拟器和伪终端的区别和联系。如果想进一步探究低层实现,可以阅读 TTY 驱动的源码 drivers/tty/tty_io.c和 line discipline
的源码 drivers/tty/n_tty.c。
本文文字及图片出自 InfoQ
Recommend
-
27
作者: HelloGitHub-ChungZH 当你逐渐厌倦了 cmd 的枯燥黑屏、powershell 的单调蓝底,可以来尝...
-
14
终端模拟器下使用双倍宽度多色Emoji字体 2017年8月更新。 多色Emoji字体 Cairo支持 较新的FreeType支持多色,但cairo-1.14.6没有默认开启支持。
-
8
折腾完https://maskray.me/blog/2016-03-13-terminal-emulator-fullwidth-color-emoji后发现canonical mode下emoji字符退格只后退了一列,后发现所有宽字符都有问题...
-
5
Wez:Rust编写的类似Powershell的终端模拟器 WezTerm 是一个 GPU 加速的跨平台终端模拟器和多路复用器,可在 Linux、macOS、Windows 10 和 FreeBS...
-
8
1 万 Star!基于 Android 平台的开源 Linux 终端模拟器-51CTO.COM 1 万 Star!基于 Android 平台的开源 Linux 终端模拟器 2022-02-14 10:29:40 Termux[1] 是一款基于 Android 平台的开源 Linux 终端模拟器...
-
7
在 Microsoft Build 2019 的大会上,微软给我们带来了一款全新设计的终端模拟器 Microsoft Terminal. 虽然过度好看的宣传片和实际的效果有着巨大的落差,但是也不影响它在 Windows 阵营里取得最高的颜值称号。
-
8
Fig CLI命令...
-
4
号称当前最快的终端模拟器alacrity 作者: dreamfly 分类: software 发布时间: 2022-10-12 09:39 作为一个后端程序员,我们每天都要和终端打交道,...
-
4
超级强大的终端模拟器-rust开发的支持gpu渲染采用lua配置的多路复用模拟器 对于后端开发人员来说,每天接触最多的就是终端了,而一款趁手的工具对于工作效率来说至关重要,可以起到事半功倍的效果。 wezterm就是一款不可多得非常好用的终端模...
-
12
在 Arch 配置 i3-wm 终端模拟器 xterm 关于怎么在 Arch 安装 i3-wm 可以查看上一篇文章 👉 https://www.cnblogs.com/sh...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK