在NetBSD中,wscons控制台驱动程序可以模拟一个VT100终端也模拟了一个Sun最近,一位新手问我为什么不能模拟终端。VT220,以及wacons模拟的终端类型和在/etc/tty文件中设置的终端类型有什么区别?这让我意识到谈论终端模拟的历史BSD开发人员很可能会有所帮助。
首先,我将谈谈最初的设计Unix操作系统时的硬件概述。然后谈谈这些硬件对其他硬件通信应用程序的支持,以及信息是如何生成的。接下来,让我们回到当前(2001),比较X窗口系统和传统的基于终端的系统Unix系统。最后,探索今天的模拟终端程序,目的是展示那些古老的Unix终端仍然有用。
本文所有的例子都取自NetBSD,但对于所有Unix就系统而言,概念是一致的 — 不管是老了PDS/Cadmus,还是年轻的BSD Solaris或Linux。
让我们回到Unix在石器时代,计算机系统通常是一个装有内存、存储设备和操作人员启动过程的大盒子。由于硬件价格昂贵,当时的系统都是多用户系统。和现在的Unix与工作站相比,当时的机器没有显示器和键盘,数据的输入和输出是通过串口线进行的电传打字机(teletypewriter),稍后则是CRT终端。
电传打字机,Unix世界称之为世界tty’,把用户按键经由串口线发送到主机;主机的响应同样经由串口线一个字母一个字母地传回点传打字机,由电传打字机内置的打印机把信息打印到纸上。
有的电传打字机只支持大写字母,有的则支持输入和打印大小写字母。通知系统只支持大写、小写或同时支持的方法Unix如果登录帐户使用小写字母,系统将假设您的终端同时支持大小写字母。但如果您使用大写字母(或您的电传输打字机将您的输入转换为大写字母),系统认为终端只支持大写字母,并在响应信息中使用大写字母,并添加前反斜杠\’:
AIX Version 4 (C) Copyrights by IMB and by others 1982, 1996. login: ESP 3004-033 YOU LOGGED IN USING ALL UPPERCASE CHARACTERS. IF YOUR WORKSTATION ALSO SUPPORTS LOWERCASE CHARACTERS, LOG OFF, THEN LOG IN AGAIN USING LOWERCASE CHARACTERS. \E\S\P'S \PASSWORD:
提供更先进的电传打字机change from black to red ribbon粗体字的功能可以通过再次输入随处可见 — 打印字母,返回打印机头(输入backspace),再次打同样的字母。没过多久,电传打字机上的打印机就被打印了CRT取代了。CRT在涂磷的玻璃表面打电子束显示字母(绿色)。此时,终端的定义变成了键盘和CRT的组合。
该终端的功能与电传打字机相同 — 击键通过串行线送到主机,主机的响应逐个字母的送回来,并由终端显示出来。终端本身没有任何处理能力,所以经常成为哑终端。如果主机发送一个f和两个fo,将显示在屏幕上foo在后面显示一个闪烁的光标(cursor)。字符集7位ASCII字符集,至今仍在Unix它在世界上被广泛使用,但也逐渐被其他竞争标准使用,如ISO8859-1或unicode,慢慢超越。
在送出’foo之后,主机还发出一个字符命令,指示移动到下一行,有时根据不同的终端设置发送另一个字符命令,要求移动到银行的开始。这些控制字符通常被称为CR (carriage return)和LF (line feed)。命令字符最初被编码ASCII前32个字符集。
32个字符很快就不够了,因为需要使用更多的命令。人们被迫使用多字符命令。这种方法通常需要控制序列引导(Control Sequence Introducer, CSI),后面是一个或多个命令字节(例如:move cursor)和数据字节(如行/列信息)。与此同时,终端制造商开始为自己的产品制定命令集,这使得事情变得更糟,因为命令集不兼容。具有代表性的命令集是DEC(Compaq)VT100/VT220 escape sequences(这样命名是因为所有命令都在前面escape’字符,ASCII 作为命令的第一个字符), ANSI codes。
Unix系统是真正的多用户系统,不同的终端可以通过标准串行协议连接到主机上。然而,哪些想要使用特殊终端的特殊功能的应用程序则必须设法应对终端的差异。在应用程序内部包含对特定终端的支持根本不是一个选项,因为这意味着使用该终端的所有应用都要实现类似的逻辑,没有可维护性。
另一种方法是将命令映射表放入主机的操作系统,将操作映射到特殊终端。这样,当应用程序想要清空整个终端屏幕或移动光标时,它会通过该表找到终端的相应命令,并将其发送到终端执行。这样,只要记住一般命令,应用程序就不必记住特定终端的命令。只需更新映射表即可支持新终端。这是一个巨大的进步!
现在有两个库负责操作映射表。System V和linux使用terminfo库。 基于BSD的termcap库将所有终端信息放入文件中,通常是/usr/share/misc/termcap. 一定要去看看!
还有一个问题没有解决: 用户如何通过终端登录并启动应用程序,系统如何知道模拟哪个终端并使用哪个命令?答案是每个终端链接到系统的特定串口(dev/ttySomething),并且文件/etc/ttys记录终端类型。(请注意:以下是BSD为例。System V使用文件/etc/inittab)
文件中记录的终端类型信息通过登录系统传输给用户shell,用户的所有应用程序都来自shell启动。可以使用应用程序termcap查询命令。
终端类型信息存储在环境变量中TERM如有必要,该变量也可以设置为其他值。此外,可以使用当前的终端线tty命令查询。
目前的工作站不再配置终端(硬件),相反,CRT通常直接连接到主机的图形系统,输入设备是键盘和鼠标,避免使用慢串行线。
对于上述模型,终端可以处理的命令集,仍然适用于今天的控制台驱动。控制台驱动是处理键盘、鼠标和显示设备输出的核心部分。它通过一个软件终端设备传递数据,该设备使用和串行设备一样的接口,因此也要在/dev/ttys中配置。和以前的终端设备一样,发送到控制台的信息也需要分析。但控制台支持更多的字符集,包括各种字符集VT100/VT220的变体,ANSI及更多。
大多数PC操作系统提供了另一种叫做虚拟控制台的机制。该机制允许用户坐在终端上(display/keyboard/mouse)面前,通常可以看到多个虚拟控制台CTRL Alt Fn切换。系统将每个虚拟控制台视为单独的线路,需要在/etc/ttys配置每一个。
我们讨论了主机和终端之间的字符数据传输,并显示在控制台上。然而,目前还没有关于图形是如何工作的答案。
让我们回去一段时间。终端设备制造商不断为其产品添加新的功能。其中之一是不止80x24文本还可以显示位图。支持此功能的命令自然是非标准的。当时没有类似的terminfo/termcap这应用程序使用标准供应程序,使用设备无关的命令来操作不同的图形终端。
渐渐地,计算机被设计成一个主运算单元(CPU)图形处理单元(GPU),两者通过线路连接,比串行线路快得多。与此同时,计算机网络也变得流行起来。
MIT一组研究人员设计了基于模块化组件的图形用户界面(GUI),组件之间的关系就像经典的主机/终端。它包含了发出命令(如清空屏幕或打开窗口)的应用过程。命令被发送到性能服务器(presentation server),对命令进行解码,并采取任何必要的操作,使屏幕变黑或画一个带框架的矩形。命令可以来自本地或远程计算机。性能服务器知道如何与显卡通信生成输出;也知道如何与鼠标/键盘通信以获得输入。输入服务器包装为事件(Event)的形式并发送给应用程序。
你熟悉上一节吗? 不?也许在我介绍了上述概念的名字之后,你会舒服得多。
前面提到的窗口系统是X窗口系统(X Window System,以下简称X)。 应用程序被称为 X client。 负责硬件访问的性能服务器是X server。 X server和X client基于X协议的通信使用TCP/IP协议栈。
Unix主机可以操作多个用户流程,一个操作多个用户流程X clients主机可以多个X server发出绘图指令。X server它可以在本机上运行,使用显卡/鼠标/键盘或远程计算机。
制造商大张旗鼓地销售和销售VT220兼容的字符终端的同时,一种称为”X终端的新面孔也悄然出现。终端基本就是只能处理输入输出,不具备任何其它处理能力的传统字符终端的翻版, 除了在X终端上运行着X server!一般来说,X终端由一个显示器、键盘、鼠标还有一个小盒子组成。这个小盒子只负责运行X server。X终端上运行的这个X server知道如何与显卡/键盘/鼠标打交道,并把输入输入传递给X clients。
一个X终端的变种就是今天的Unix工作站,把CPU,显卡,IO设备都装进一个PC当中。这个工作站运行和硬件通讯的X server,并于若干X clients协同工作。
截止目前,我们谈到了Unix世界里经典的终端的概念,谈到了和主机-终端架构类似的X窗口系统。现在,我们有了X,任何人都能把PC变成一个工作站,大可以忘掉那些来回传递字符、escape sequence的晦涩难懂的终端的概念了。
但是,我们真得可以吗?让我们来看看Unix系统是如何通讯的。
今天,大多数和操作系统的互动仍旧发生在命令行界面,比如列出一个目录的内容,启动一个进程,观测进程的输出。以上既可以通过X也可以通过命令行环境。这里所说的命令行环境通常就是运行在系统控制台,或某个虚拟控制台,或X桌面中的终端窗口中的shell。
如果使用系统控制台或虚拟控制台,很明显传统的终端处理方式仍然在用,因为它是基于命令的输入输出的基础。这对基于行的程序如ls或cat,以及基于屏幕的程序如vi和top都同样适用,它们都使用terminfo或termcap库以查询控制台的功能。
但我们刚刚达成一致,控制台不再有用,因为可以利用X访问系统。可以用xterm或konsole(KDE),或gnome-terminal(Gnomes)打开一个终端窗口。在下面的例子中,我们使用xterm,但其它两个选择实际上也差不多。当启动X并运行xterm,会打开一个矩形的窗口,里面有一个正在运行的shell。你可以输入命令,该命令的输出就显示在xterm窗口中。这个时候,是X server捕获键盘输入并将其送到xterm进程。
xterm进程连接到shell进程,键盘输入因此由xterm送往shell — 就像虚拟控制台和远古的哑终端一样。shell进程从标准输入读取输入,处理命令,输出则经标准输出送回给xterm进程。xterm进而通过X协议指示X server重绘xterm窗口。
如果应用程序要清空屏幕或将光标移往指定位置又会发生些什么?就像以前一样,应用知道它所连接的终端类型,因此使用terminfo/termcap查询终端属性,并把相应的escape sequences发给xterm。xterm进程识别并解析命令,但并不把这些基于字符的命令直接发给X server,而是把该命令转为X server可识别的语言(X协议)。
有两个细节值得关注。
首先,xterm和shell的通讯是通过Unix正常的终端IO例程进行的 — 对X server和运行在命令行环境的应用之间通讯而言,X没有’发明’任何特殊的机制,而只是由xterm在两种环境之间充当’翻译’。这意味着Unix的终端处理机制在30年后的环境中依然有用。
其次,是xterm和X server之间的通讯。 和其它任何图形应用一样,xterm进程发送绘图请求给X server — 一个大的白色的矩形,一个小的黑色的矩形,移动屏幕上的一块区域到另一个位置,当然还有使用X的字库机制以使用特定的字型并将字符显示到表现服务器上。尽管自身不提供特殊的命令,xterm允许你更改X server使用的字库(字型)和其它一些配置。同时按下CTRL键和鼠标左键,你能看到调整字体的弹出窗口 — 这正是xterm向X server发出的请求。
如你所见,GUI并未取代Unix系统中的传统概念,而是与其协同工作,这样一来,既有的应用无需移植就可以运行在窗口环境中;终端最早代表一种硬件,现在则更多是软件的概念。通过这样的传承,’老的’和’新的’技术具有同样的生存权。它们并非彼此竞争,而是协同工作。
Unix的简单好用让它在这么多年以后仍然生机勃勃。
结束本文之前,需要澄清一下我故意遗漏了一些内容 — 用于xterm和shell之间通讯的(伪)终端同样应用于rsh和ssh,也应用于将在不同主机上传递数据的多个进程伪装成就像在同一个主机上一样。同样,有关X系统也有很多概念没有提到,我马上能想到的有窗口管理器(window manager)和会话管理(session management)。这些都有待以后完善。
我希望你在读这篇文章时得到了乐趣和我写它时一样多。