线路规程模块 (ldterm)
ldterm 线路规程是终端的常用线路规程。
此线路规程符合 POSIX 同时也确保与 BSD 接口的兼容性。 支持后一个线路规程仅仅是为了与以往的应用程序兼容。 出于可移植性的考虑,强烈建议您在新的应用程序中使用 POSIX 接口。
此部分描述由 ldterm 线路规程提供的功能。 有关控制 ldterm的更多信息,请参阅 Files Reference 中的 "termios.h File"
阅读以下部分以了解更多有关 ldterm 线路规程的内容:
终端参数
用于控制某些终端 I/O 特征的参数在 termios 结构中指定,如 termios.h 文件中所定义。 termios 结构包含(但不限于)以下组成部分:
- tcflag_t c_iflag
- 输入方式
- tcflag_t c_oflag
- 输出方式
- tcflag_t c_cflag
- 控制方式
- tcflag_t c_lflag
- 本地方式
- cc_t c_cc[NCCS]
- 控制字符。
该tcflag_t和cc_t在 termios.h 文件中定义了无符号整数类型。 NCCS 符号也定义在 termios.h 文件中。
进程组会话管理(作业控制)
控制终端将会话中一个与它关联的进程组识别为前台进程组。 会话中的所有其他进程组被指定为后台进程组。 前台进程组在处理信号时扮演了一个特殊角色。
支持作业控制的命令解释器进程诸如 Korn shell(ksh 命令)和 C shell(csh 命令)通过将相关进程置于单个进程组中和将此进程组与终端相关联, 可将终端分配到不同的作业或者进程组。 终端的前台进程组可由进程设置或者检查,假定许可权需求是满足的。 终端驱动程序通过限制非前台进程组中的进程访问终端来辅助作业的分配。
终端访问控制
如果某个不在控制终端前台进程组中的进程企图从控制终端中读取,那么向该进程的进程组发送一个 SIGTTIN 信号。 但是,如果读取进程忽略或阻塞 SIGTTIN 信号或者如果读取进程的进程组是孤立的,那么读取请求返回值 -1、将 errno 全局变量设为 EIO 并且不发送任何信号。
如果某个不在控制终端前台进程组中的进程企图写入控制终端,那么向该进程的进程组发送一个 SIGTTOU 信号。 但是, SIGTTOU 信号的管理取决于在以下标志中定义的 TOSTOP 标志:c_lflagtermios 结构的字段。 如果未设置 TOSTOP 标记,或者设置了 TOSTOP 标记且进程忽略或阻塞 SIGTTOU 信号,那么将允许该进程写入终端并且不发送 SIGTTOU 信号。 如果 TOSTOP 标记已设置、写进程的进程组是孤立的且写进程未忽略或阻塞 SIGTTOU 信号,那么写请求返回值 -1、将 errno 全局变量设为 EIO 并且不发送任何信号。
对某些设置终端参数的函数(tcsetattr、tcsendbreak、tcflow 和 tcflush)的处理采取与写请求同样的方式,不同之处是 TOSTOP 标记被忽略。 当设置 TOSTOP 标记时,其效果和终端写请求的效果完全一样。
读取数据和输入处理
根据终端设备文件规范与否,可使用两种常规的输入处理。 此外,输入字符将根据以下内容进行处理:c_iflag和c_lflag字段。 这样的处理可包含回传,即将字符立即传送回发送它们的终端。 回传对能够以全双工方式运作的终端是有帮助的。
根据 O_NONBLOCK 标记是由 open 还是 fcntl 子例程设置的, 可以两种方法处理读取请求。 如果 O_NONBLOCK 标记未设置,那么阻塞读取请求直到可获取数据或者接收到信号为止。 如果 O_NONBLOCK 标记已设置,那么读取请求在以下三种方式之一下无阻塞地完成。
- 如果有足够的可用数据来满足整个请求,那么读取请求将成功完成并返回读取的字节数。
- 如果没有足够的可用数据来满足整个请求,那么读取请求成功完成,已读取尽可能多的数据,并返回它能够读取的字节数。
- 如果没有可用数据,读取请求将返回值为-1并将errno全局变量设置为EAGAIN
数据的可用性取决于输入处理方式规范与否。 规范或不规范方式可用 stty 命令设置。
规范方式输入处理
在规范方式下,输入处理 (ICANON 标志设置在c_lflagtermios 结构的字段) ,以行为单位处理终端输入。 行是通过换行 (ASCII LF) 字符、文件结束 (EOF) 字符或者行结束 (EOL) 字符来定界的。 这意味着尝试读取的程序被阻塞直到整个行已输入或者已经收到信号为止。 同样,不管在读取请求中指定多少字符,返回时不会超过一行。 然而,每次也不必读取一整行。 可以在一个读取请求中指定任何数量的字符而不丢失信息。 在输入期间,将执行擦除和终止处理。
- 擦除字符
- (退格,缺省情况)擦除最后输入的那个字符
- “字擦除”字符
- (Ctrl-W 按键序列,缺省情况)擦除当前行中最后输入的那个字,而非任何在前面的空格或制表符
(字定义为非空白字符的序列,制表符被认为是若干空白。) “擦除”字符和“字擦除”字符的擦除范围都不超过行首。
- 行删除符
- (Ctrl-U 序列,缺省情况)删除整个输入行并可选择输出一个换行字符
所有这些字符都在按键基础上生效,与任何可能已完成的退格或者跳格操作无关。
- “重显”字符
- (Ctrl-R 序列,缺省情况)显示后跟未曾读取的先前行中字符的新行
如果从屏幕上正常擦除的字符被程序违规输出,那么也会自动发生重显。 这些字符被重新显示,好像它们正在回传。 因此,如果 ECHO 标志未在c_lflagtermios 结构的字段,不打印字符。 通过在“擦除”字符和“行删除”字符之前使用转义字符 \(反斜杠)可以逐字输入前两种字符,这种情况下不读取转义字符。 “擦除”字符、“字擦除”字符、“行删除”字符是可以更改的。
非规范方式输入处理
在非规范方式下输入处理 (-ICANON 标志设置在c_lflagtermios 结构的字段) ,输入字节未组装成行,并且不会发生擦除和终止处理。
- 最小
- 代表当读取请求成功时应该接收的字节的最小数目。
- 时间
- 用于超时脉冲和短期数据传输的粒度为 0.1 秒的计时器。
系统的 MIN 和 TIME 成员的值c_cc数组用于确定如何处理接收的字节。 可以用 stty 命令设置 MIN 和 TIME 值。 MIN 和 MAX 具有范围从 0 到 265 的值。 MIN 和 TIME 的四种可能组合和它们的交互作用在后续段落中描述。
情况 A:MIN0 和 TIME0
在这种情况下,TIME 作为字节间计时器提供服务,当接收到第一个字节后激活它且每次接收到一个字节时对它进行复位。 如果在字节间计时器到时前接收到 MIN 字节,那么满足读取请求。 如果在接收到 MIN 字节之前该计时器到时,那么在那个点接收到的字符将返回到用户。 如果 TIME 到时,那么至少返回一个字节。 (除非接收到一个字节,否则该计时器不会处于启用状态。) 读取操作受到阻塞,直到由于接收到第一个字节而激活 MIN 和 TIME 机制或者接收到信号为止。
情况 B:MIN0 和 TIME = 0
在这种情况下,仅 MIN 是有意义的;计时器没有意义(TIME 值为 0)。 无法满足暂挂读取请求(阻塞),直到接收到 MIN 字节或者接收到信号为止。 使用这种方案读取基于记录的终端 I/O 的程序可能在读取操作中发生无限期的阻塞。
情况 C:MIN = 0 和 TIME0
在这种情况下,因为 MIN 的值为 0,TIME 不再代表一个字节间计时器。 现在它作为读取计时器提供服务,一旦处理读取请求就激活它。 一旦接收到一个字节或者当读取计时器到时就可满足读取请求。 注意如果该计时器到时,那么不返回任何字节。 如果该计时器未到时,那么仅当接收到一个字节后才能满足读取请求。 在这种情况下,读取操作不会无限期阻塞而等待一个字节。 如果当启动读取请求后,在以 TIME x 0.1 秒而指定的周期内未接收到任何字节,那么读取请求返回值 0,未读取任何数据。
情况 D:MIN = 0 和 TIME = 0
在这种情况下,不等待输入更多的字节而返回请求的字节数最小值或者当前可用的字节数的最小值。 如果没有字节可用,读取请求返回值 0,未读取任何据。
方案 A 和 B 的存在是为了处理触发方式的活动(例如文件传送程序),在此活动中程序一次需要至少处理 MIN 变量指定数目的字符。 方案 A 中,字节间计时器作为一种安全措施而激活。 方案 B 中,关闭该计时器。
方案 C 和 D 的存在是为了处理受限于单个字符的传送程序。 这些方案极适用于基于屏幕的应用程序,这些应用程序需要在刷新屏幕前了解某个字符是否存在于输入队列中。 方案 C 中,激活该计时器。 方案 D 中,关闭该计时器。 如果使用过度,方案 D 可能导致性能问题;但是与设置 O_NONBLOCK 标记来执行读取请求相比最好还是使用它。
写入数据和输出处理
当写入一个或者多个字符时,一旦先前写入的字符显示出来,就将当前写入的字符传输到终端。 (通过当输入字符到达时将其置入输出队列的方式来回传这些输入字符。) 如果进程产生字符的速度比显示字符更快,那么当输出队列超出特定界限时进程会被暂挂。 当队列内容清除至某一个阈值时,程序恢复运行。
调制解调器管理
如果 CLOCAL 标志是在c_cflagtermios 结构的字段,连接不依赖于调制解调器状态行的状态。 如果 CLOCAL 标记已清除,那么调制解调器状态行被监视。 在正常情况下,open 功能等待调制解调器完成连接。 但是,如果设置了 O_NONBLOCK 或者 CLOCAL 标记,那么打开功能不等待连接而立即返回。
如果 CLOCAL 标志未在c_cflag控制终端的终端接口检测到 termios 结构的字段和调制解调器断开连接,将 SIGHUP 信号发送到与该终端相关联的控制进程。 除非已经做了其他安排,否则此信号导致进程终止。 如果忽略或者捕获 SIGHUP 信号,那么任何随后的读取请求返回一个文件结束指示信息直到终端关闭为止。 任何随后的对终端的写请求返回值 -1 且将 errno 全局变量设为 EIO 直到设备关闭为止。
关闭终端设备文件
关闭终端设备文件的最后一个进程会使得所有输出被发送到该设备并使所有输入被废弃。 然后,如果 HUPCL 标志设置在c_cflagtermios 结构的字段和通信端口支持断开连接功能,终端设备执行断开连接。