注意:本文是作者自己对终端的理解,为了解开自己心中困惑查阅了一些资料后有感而写,很多地方术语表述并不精确,自己的体会而已,仅供参考。
计算机刚被发明的时候,并没有显示器和键盘。后来的Unix主机也没有,其输入和输出是通过一个串口线连接到专门的输入输出设备上,这个设备就叫做终端,最早出现的是一种电传打字机teletype,所以终端就使用tty三个字母表示了。
主机 ---------(串口线)--------------终端设备(包括键盘、显卡和鼠标等)
终端设备一般包括用于输入的键盘和用于输出的显示器,由于主机不直接管理终端的键盘和显示器,而是把终端作为一个物理整体对待,所以主机和终端之间是通过一组控制命令(协议)来交互的。按照Unix中一切都是文件的概念,终端设备也一样,对终端设备的读就是获取用户的输入,而对终端设备的写就是输出。
需要注意的是,微软的DOS和Windows中很少使用终端的概念,因为这些系统出现在本身就带有键盘和显示器的机器上。这些系统更倾向于直接管理键盘和显示器(处理键盘控制器和直接写显存),而不是把它们作为一个终端来使用。
早期终端型号很多,其显示能力也各不相同,控制指令也不统一,这给编程带来了很大麻烦,为了规范终端的显示能力和控制指令,相继出现了一些标准:ANSI,VT100等。慢慢地所有设备都遵循这些标准来设计和实现了。相应的也出现了设备无关的编程接口库,如termcap,terminfo(/lib/libtinfo.so)等。这两个库还是很原始的,只是屏蔽了不同终端的控制指令,并没有提供更高级的功能,less工具依赖于libtinfo.so。为了便于实现类似菜单、窗口等字符模式下的高级显示方式,出现了著名的curses库。像vim,emacs等编辑器,以及info工具都是基于curses库的。
随着计算机的发展,几乎所有的机器都内建了键盘和显卡。在这种条件下,机器本身集合了主机和终端于一身。出现了两种使用设备的方式:一是还是按照传统的终端方式使用内建的键盘和显卡,二是直接控制键盘和显卡。第一种方式的优点是原来使用终端的程序不用改动,就可以直接运行,代价是必须模拟一个终端设备,把对这个终端设备的操作映射到对键盘和显卡的操作。
程序-------模拟的终端-------内建的键盘和显卡
第二种方式下,缺点是原来使用终端的程序必须重新编写。优点是可以充分利用内建显卡的性能,而不局限于ANSI,VT100等终端能力的限制。由于ANSI,VT100等出现很早,所以并未有提供像素控制的能力,所以现在所有的图形化界面程序都是基于第二种方式。
就Linux系统来说,文本模式下仍然支持传统的终端方式使用内建的键盘和显卡,并且模拟出了多个终端,可以通过Alt+F1,Alt+F2,...来切换。这样一个使用终端的程序就可以不用修改的使用真正的串口连接的终端设备(现在很少了),也可以使用通过内建显卡和键盘模拟的虚拟终端了。更需要说明的是,Linux更进一步,在内核层还提供了纯粹的虚拟终端设备,用于支持网络程序,如ssh,telnet等。之所以说它纯粹是指这种终端没有对应的硬件,更合适的名字是伪终端(pty)。
Windows平台上的putty程序(模拟终端)--------网络-----伪终端------Linux主机
Linux平台X环境下的xterm程序(模拟终端)-----伪终端--- Linux主机
刚才也说了,终端只支持文本模式显示,所以Linux下的图形境X也是直接控制键盘和显卡的。需要注意的是,Linux有一种framebuffer模式,启动后能同时支持终端模式和图形模式两种方式来使用显卡。
程序--------frambuffer API---------直接写显存
程序--------curses API---(终端指令)----模拟终端(/dev/tty1)--------映射为写显存