终端I/O之综述
终端I/O有两种不同的工作模式:
- 规范模式输入处理(Canonical mode input processing)。在这种模式中,终端输入以行为单位进行处理。对于每个读要求,终端驱动程序最多返回一行。
- 非规范模式输入处理(Noncanonical mode input processing)。输入字符并不组成行。
如果不作特殊处理,则默认模式是规范模式。
V7和较早的BSD风格类的终端驱动程序支持三种终端输入模式:(a)精细加工模式(输入组成行,并对特殊字符进行处理);(b)原始模式(输入不组成行,也不对特殊字符进行处理);(c)cbreak模式(输入不组成行,但对某些特殊字符进行处理)。
终端设备是由一般位于内核中的终端驱动程序控制的。每个终端设备有一个输入队列和一个输出队列,如图18-1所示。
图18-1 终端设备的输入、输出队列逻辑结构
将图18-1转换为如下图所示更容易理解:
对此图要说明以下几点:
- 如果打开了回显功能,则在输入队列和输出队列之间有一个隐含的连接。
- 输入队列的长度MAX_INPUT是有限值,当一个特定设备的输入队列已经填满时,系统对此作何种处理依赖于实现。大多数UNIX系统的处理方式是回显响铃字符。
- 图中没有显示另一个输入限制MAX_CANON,它是一个规范模式输入行中的最大字节数。
- 虽然输出队列通常也是有限长度,但是程序并不能获得这个定义其长度的常量,这是因为当输出队列将要填满时,内核使写进程休眠直至写队列中有可用的空间,所以程序无需关心该队列的长度。
-
我们可以使用tcflush函数刷清(flush)输入或输出队列。
大多数UNIX系统在一个称为终端行规程(terminal line discipline)的模块中进行规范处理。它是位于内核通用读、写函数和实际设备驱动程序之间的模块(见图18-2)。
图18-2 终端行规程
所有我们可以检测和更改的终端设备特性都包含在termios结构中。该结构定义在头文件<termios.h>中。
struct termios {
tcflag_t c_iflag; /* input flags */
tcflag_t c_oflag; /* output flags */
tcflag_t c_cflag; /* control flags */
tcflag_t c_lflag; /* local flags */
cc_t c_cc[NCCS]; /* control characters */
};
粗略而言,输入标志由终端设备驱动程序用来控制字符的输入(剥除输入字节的第8位,允许输入奇偶校验等等),输出标志则控制驱动程序输出(执行输出处理、将换行符映射为CR/LF等),控制标志影响到RS-32串行线(忽略调制解调器的状态线、每个字符的一个或两个停止位等等),本地标志影响驱动程序和用户之间的接口(回送的开或关、可视的擦除字符、终端产生的信号启用以及对后台输出的作业控制停止信号等)。
类型tcflag_t的长度足以保存每个标志值。它经常被定义为unsigned int或者unsigned long。c_cc数组包含了所有可以更改的特殊字符。NCCS是该数组的长度,一般介于15-20之间(大多数UNIX系统定义的特殊字符较POSIX所定义的11个要多)。cc_t类型的长度足以保存每个特殊字符,而且它往往是unsigned char型的。
表18-1至表18-4列出了所有可以进行更改以影响终端设备特性的终端标志。注意,虽然Single UNIX Specification定义了所有平台都支持的公共子集,但是各平台还有自己的扩充部分。
表18-1 c_cflag终端标志
表18-2 c_iflag终端标志
表18-3 c_lflag终端标志
表18-4 c_oflag终端标志
表18-5列出了Single UNIX Specification所定义的对终端设备进行操作(检测和更改终端设备的特性)的的各个函数。http://www.cnblogs.com/nufangrensheng/p/3513642.html中已说明了 tcgetpgrp、tcgetsid和tcsetpgrp函数。)
表18-5 终端I/O函数总览
注意,对终端设备,Single UNIX Specification没有使用经典的ioctl,而使用了表18-5中列出的13个函数。这样做的理由是:对于终端设备的ioctl函数,其最后一个参数的数据类型随执行动作的不同而不同。于是,这使得对参数进行类型检查成为不可能。
虽然对终端设备进行操作只有13个函数,但是表18-5中头两个函数(tcgetattr和tcsetattr)能处理大约70中不同的标志(见表18-至表18-4)。此外,对于终端设备有大量的选项可供使用,对一个特定设备(终端、调制解调器、激光打印机等等)还要决定所需的选项,这些都使对终端设备的处理变得异常复杂。
表18-5中列出的13个函数之间的关系如图18-3所示:
图18-3 与终端有关的函数之间的关系