Skip to content

终端libtmt库有啥用

Author: whsu First post: 2025-11-18 15:07 Last modified: 2025-11-18 15:07

Linux终端模拟器


Linux 命令行

熟悉 Linux 的同学可能知道,在 Linux 环境下,命令行是用户界面中的“一等公民”。

我们可以通过各种类型的终端来操作命令行:桌面环境提供方便的“终端模拟器”让我们在图形界面中使用终端;某些发行版也提供 ctrl+shift+数字切换的 tty 终端;安装了 ssh server 的机器可以通过远程连接上一个终端;某些嵌入式 Linux 系统提供串口终端;而screen/tmux等工具提供了可以随时切换和保留状态的终端。

Linux 系统并不关心我们使用的终端类型。在它看来,不同的终端就是一条双向字节流通道。用户通过敲击键盘,通过终端向通道发送信息;而命令执行的结果也通过通道返回终端,并由终端展示给用户。

深究起来,这一块可以展开很深:例如字节流被系统抽象为了字符设备 /dev/tty*/dev/pts;标准输入输出流 stdin stdout 和 stderr 最终也是定向到了此处;对于输入输出系统内部还存在 Line Discipline 等。如此种种暂且按下不表。

终端转义序列

前面说到:终端负责读取用户的输入,并向用户展示命令运行的结果。除了将可显示的字符在对应的位置(行、列)上显示外,终端还支持很多高级功能,例如:输出不同颜色的字体、更改光标位置以在任意位置输出文本等等。正是这些高级功能使得 vimgdb 这样具有命令行用户界面的程序的编写成为可能。

控制终端行为的字符序列名为转义序列,是由字符 \033(ASCII ESC)开头的序列。转义序列控制终端行为有国际标准 ANSI X3.64ISO/IEC 6429。符合这个标准的终端,可以称之为 ANSI 终端。现代终端支持的转义序列扩展更多,例如 xterm 标准,支持了彩色字体。

可以在自己的终端尝试输出转义序列。例如,清屏序列的十六进制表示是:

0x1b 0x5b 0x32 0x4a

在命令行中输入:

shell
printf '\x1b\x5b\x32\x4a'
printf '\033[2J' # alternative

就可以发现命令行清屏了。

终端状态机

终端不仅要处理系统发来的转义序列,还要处理终端自身的状态。终端的状态包括:

  • 终端各个行列存在什么字符,各个字符的属性(颜色、粗细、下划线等)是什么

  • 终端的光标在哪个位置

  • 终端之前收到的不完整转义序列是什么

  • ...

在收到常规字符或转义序列后,终端需要根据收到的信息和当前状态,变为新的状态。例如:

收到的状态变化
常规字符光标所在位置字符变为收到的字符,光标位置前进一个字符
转义序列(清屏)清空所有位置的字符
转义序列(加粗)设置内部状态,等收到常规字符后给对应位置设置加粗属性
......

终端需要维护的所有状态,统称终端状态机。

Libtmt 有啥用?

libtmt 和它的大哥 libtsm 一样,都是处理终端转义序列,并维护终端状态机的库。需要注意的是,libtmt/libtsm 等库并不负责如何具体向用户显示终端内容,而只是根据收到的字节流(字符、转义序列),维护终端状态机,仅此而已。用户界面可以通过读取 libtmt 的状态来实时更新最新的终端内容,让用户看见。

上面已经提到,终端的类型有很多种。笔者想实现的终端是物理终端。通过两根串口线,笔者的物理终端和 Linux 主机进行通信。而 libtmt 通过读取串口更新终端内部状态,而一个RGB888 屏幕实时地读取 libtmt 的状态,将终端展示给用户。

粤ICP备2024206975号