Do not panic!
分类: LINUX
2016-08-06 18:19:37
原文地址:对于Linux内核tty设备的一点理解 作者:tekkamanninja
虽然一直做嵌入式Linux,宿主机和开发板通信天天都在用tty设备通信,但是其实自己对TTY设备及终端的概念认识几乎是0。对于Linux内核的终端、tty、控制台等概念的认识很模糊。由于在学习的时候碰到了重定向console的问题,所以借机学习下tty的知识。以下是我对tty的认识总结,信息来源于网络和内核文档。参考资料见文章末尾。
tty一词源于Teletypes,或Teletypewriters,它是最早出现的一种终端设备,类似电传打字机,由生产。最初tty是指连接到Unix系统上的物理或者虚拟终端。终端是一种字符型设备,通常使用tty来统称各种类型的终端设备。随着时间的推移,当通过串行口能够建立起终端连接后,这个名字也用来指任何的串口设备。它还有多种类,例如串口(ttySn、ttySACn、ttyOn)、USB到串口的转换器(ttyUSBn),还有需要特殊处理才能正常工作的调制解调器(比如传统的WinModem类设备)等。tty虚拟设备支持虚拟控制台,它能通过键盘及网络连接或者通过xterm会话登录到计算机上。
终端按照其自身能力分类,可以分为: 1、哑终端(瘦客户端) 早期的计算机终端是通过串行RS-232通信的,它只能解释有限数量的控制码(CR,LF等),但没有能力处理执行特殊的转义序列功能(如清行、清屏或控制光标的位置)。简单来说就是处理能力有限的终端机,他们一般基本上只具有和机械电传打字机类似的有限功能。这种类型的终端称为哑终端。现在仍然在现代类Unix系统上得到支持,通过设置环境变量TERM=dumb。哑终端有时用来指任何类型的通过RS-232连接的传统计算机终端,不对数据进行本地处理或本地执行用户程序的串行通信终端。哑终端有时也指功能有限,只有单色文本处理能力或直接传输每一个键入的字符而不等待主机轮询的公共计算机终端。 2、智能终端(胖客户端) 智能终端就是有能力处理转义序列,也就是说处理能力较强的终端机。
Linux系统的终端设备一般有以下几种:
- 系统控制台/dev/console
/dev/console是系统控制台,是与操作系统交互的设备。系统所产生的信息会发送到该设备上。平时我们看到的PC只有一个屏幕和键盘,它其实就是控制台。目前只有在单用户模式下,才允许用户登录控制台/dev/console。(可以在单用户模式下输入tty命令进行确认)。
console有缓冲的概念,为内核提供打印输出。内核把要打印的内容装入缓冲区__log_buff,然后由console来决定打印到哪里(比如是tty0还是ttySn等)。console指向激活的终端。历史上,console指主机本身的屏幕和键盘,而tty指用电缆链接的其它位置的控制台。某些情况下console和tty0是一致的,就是当前所使用的是虚拟终端,也是激活虚拟终端。所以有些资料中称/dev/console是到/dev/tty0的符号链接,但是这样说现在看来是不对的:根据内核文档,在2.1.71之前,/dev/console根据不同系统设定,符号链接到/dev/tty0或者其他tty*上,在2.1.71版本之后则完全由内核代码内部控制它的映射。
如果一个终端设备要实现console功能,必须向内核注册一个struct console结构,一般的串口驱动中都会有。如果设备要实现tty功能,必须要内核的tty子系统注册一个struct tty_driver结构,注册函数在drivers/tty/tty_io.c中。一个设备可以同时实现console和tty_driver,一般串口都这么做。
- 当前控制台: /dev/tty
这是应用程序中的概念,如果当前进程有控制终端(Controlling Terminal),那么/dev/tty就是当前进程控制台的设备文件。对于你登录的shell,/dev/tty就是你使用的控制台,设备号是(5,0)。不过它并不指任何物理意义上的控制台,/dev/tty会映射到当前设备(使用命令“tty”可以查看它具体对应哪个实际物理控制台设备)。输出到/dev/tty的内容只会显示在当前工作终端上(无论是登录在ttyn中还是pty中)。你如果在控制台界面下(即字符界面下)那么dev/tty就是映射到dev/tty1-6之间的一个(取决于你当前的控制台号),但是如果你现在是在图形界面(Xwindows),那么你会发现现在的/dev/tty映射到的是/dev/pts的伪终端上。/dev/tty有些类似于到实际所使用终端设备的一个联接。
你可以输入命令 “tty",将显示当前映射终端如:/dev/tty1或者/dev/pts/0等。也可以使用命令“ps -ax”来查看其他进程与哪个控制终端相连。
在当前终端中输入 echo “tekkaman” > /dev/tty ,都会直接显示在当前的终端中。
/dev/ttyn是进程虚拟控制台,他们共享同一个真实的物理控制台。
如果在进程里打开一个这样的文件且该文件不是其他进程的控制台时,那该文件就是这个进程的控制台。进程printf数据会输出到这里。在PC上,用户可以使用alt+Fn切换控制台,看起来感觉存在多个屏幕,这种虚拟控制台对应tty1~n,其中 :
/dev/tty1等代表第一个虚拟控制台
例如当使用ALT+F2进行切换时,系统的虚拟控制台为/dev/tty2 ,当前控制台(/dev/tty)则指向/dev/tty2
在UNIX系统中,计算机显示器通常被称为控制台(Console)。它仿真了类型为Linux的一种终端,并且有一些设备特殊文件与之相关联:tty0、tty1、tty2等。当你在控制台上登录时,使用的是tty1。使用Alt+[F1—F6]组合键时,我们就可以切换到tty2、tty3等上面去。
你可以登录到不同的虚拟控制台上去,因而可以让系统同时有几个不同的会话存在。
而比较特殊的是/dev/tty0,他代表当前虚拟控制台,是当前所使用虚拟控制台的一个别名。因此不管当前正在使用哪个虚拟控制台(注意:这里是虚拟控制台,不包括伪终端),系统信息都会发送到/dev/tty0上。只有系统或超级用户root可以向/dev/tty0进行写操作。tty0是系统自动打开的,但不用于用户登录。在Framebuffer设备没有启用的系统中,可以使用/dev/tty0访问显卡。
伪终端(Pseudo Terminal)是终端的发展,为满足现在需求(比如网络登陆、xwindow窗口的管理)。它是成对出现的逻辑终端设备(即master和slave设备, 对master的操作会反映到slave上)。它多用于模拟终端程序,是远程登陆(telnet、ssh、xterm等)后创建的控制台设备。
历史上,有两套伪终端软件接口:BSD接口:较简单,master为/dev/pty[p-za-e][0-9a-f] ;slave为 /dev/tty[p-za-e][0-9a-f] ,它们都是配对的出现的。例如/dev/ptyp3和/dev/ttyp3。但由于在编程时要找到一个合适的终端需要逐个尝试,所以逐渐被放弃。Unix 98接口:使用一个/dev/ptmx作为master设备,在每次打开操作时会得到一个master设备fd,并在/dev/pts/目录下得到一个slave设备(如 /dev/pts/3和/dev/ptmx),这样就避免了逐个尝试的麻烦。由于可能有好几千个用户登陆,所以/dev/pts/*是动态生成的,不象其他设备文件是构建系统时就已经产生的硬盘节点(如果未使用devfs、udev、mdev等) 。第一个用户登陆,设备文件为/dev/pts/0,第二个为/dev/pts/1,以此类推。它们并不与实际物理设备直接相关。现在大多数系统是通过此接口实现pty。我们在X Window下打开的终端或使用telnet 或ssh等方式登录Linux主机,此时均通过pty设备。例如,如果某人在网上使用telnet程序连接到你的计算机上,则telnet程序就可能会打开/dev/ptmx设备获取一个fd。此时一个getty程序就应该运行在对应的/dev/pts/*上。当telnet从远端获取了一个字符时,该字符就会通过ptmx、pts/*传递给 getty程序,而getty程序就会通过pts/*、ptmx和telnet程序往网络上返回“login:”字符串信息。这样,登录程序与telnet程序就通过“伪终端”进行通信。
- telnet<--->/dev/ptmx(master)<--->pts/*(slave)<--->getty
如果一个程序把 pts/*看作是一个串行端口设备,则它对该端口的读/写操作会反映在该逻辑终端设备对的另一个/dev/ptmx上,而/dev/ptmx则是另一个程序用于读写操作的逻辑设备。这样,两个程序就可以通过这种逻辑设备进行互相交流,这很象是逻辑设备对之间的管道操作。对于pts/*,任何设计成使用一个串行端口设备的程序都可以使用该逻辑设备。但对于使用/dev/ptmx的程序,则需要专门设计来使用/dev/ptmx逻辑设备。
通过使用适当的软件,就可以把两个甚至多个伪终端设备连接到同一个物理串行端口上。
串行端口终端(Serial Port Terminal)是使用计算机串行端口连接的终端设备。计算机把每个串行端口都看作是一个字符设备。有段时间串行端口设备通常被称为终端设备,那时它的最大用途就是用来连接终端,所以这些串行端口所对应的设备名称是/dev/tts/0(或/dev/ttyS0)、/dev/tts/1(或/dev /ttyS1)等,设备号分别是(4,0)、(4,1)等(对应于win系统下的COM1、COM2等)。若要向一个端口发送数据,可以在命令行上把标准输出重定向到这些特殊文件名上即可。
例如,在命令行提示符下键入:echo tekkaman> /dev/ttyS1会把“tekkaman”发送到连接在ttyS1(COM2)端口的设备上。
在2.6以后的内核中,部分三星芯片(例如S3C24x0等)将串口终端设备节点命名为ttySACn。TI的Omap系列芯片从2.6.37开始芯片自带的UART设备开始使用专有的的omap-uart驱动,故设备节点命名为ttyOn,以区别于使用8250驱动时的设备名“ttySn”。
其实在理解以上概念的时候,如果了解终端的发展历程,就可以比较容易理解tty、终端的概念。所以请大家阅读最后推荐的wiki英文网页,有助于理解上面的概念。当然,内核文档也是必不可少的参考资料,我顺手翻译了一下。还针对很多不同的字符设备存在有很多其它种类的终端设备特殊文件,例如针对ISDN设备的/dev/ttyIn终端设备等。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
内核文档/Documentation/devices.txt翻译节选:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
推荐阅读:
wiki百科关于终端的网页: | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以上是我参考了网上的资料后对tty的认识整理,参考资料如下:
终端tty、虚拟控制台、FrameBuffer的切换过程详解