下一页 上一页 目录

11. 流控制 (握手)

流控制(= 握手 = 步调控制)是为了防止过快的字节流使终端、计算机、调制解调器或其他设备溢出。溢出是指设备无法足够快地处理接收到的内容,从而丢失字节和/或产生其他严重错误。流控制的作用是暂停字节流,直到终端(例如)准备好接收更多字节。流控制发送信号以停止字节流,方向与它想要停止的字节流方向相反。流控制必须在终端和计算机上都进行设置。

流控制有两种类型:硬件流控制和软件流控制(Xon/Xoff 或 DC1/DC3)。硬件流控制使用专用信号线,如 RTS/CTS 或 DTR/DSR,而软件流控制通过在正常数据线中发送 DC1 或 DC3 控制字节来发出信号。对于硬件流控制,电缆必须正确接线。

两个串行端口之间电缆中的数据字节流是双向的,因此需要考虑两个不同的流(和线路)

  1. 从计算机到终端的字节流
  2. 从终端键盘到计算机的字节流。

11.1 为什么需要流控制?

您可能会问:“为什么不以足够慢的速度发送,使设备不会溢出,从而不需要流控制呢?” 这是可能的,但通常比更快地发送并使用流控制要慢得多。原因之一是不能将串行端口波特率设置为任何期望的速度,例如 14,500,因为只有离散数量的选择可用。最好的选择是选择比设备能够跟上的速度稍高的速率,然后使用流控制使事情正常工作。

如果决定不使用流控制,则必须将速度设置得足够低,以应对最坏情况。对于终端,这是指当向其发送转义序列以执行比正常情况花费更多时间的复杂任务时。在调制解调器(带有数据压缩但没有流控制)的情况下,从计算机到调制解调器的速度必须足够慢,以使相同的速度可以在电话线上使用,因为在最坏的情况下,数据是随机的并且无法压缩。如果未能使用流控制,则速度(在启用数据压缩的情况下)将不会比不使用任何压缩时更快。

缓冲区在处理短时间内最坏情况方面有所帮助。缓冲区存储传入速度太快而无法立即处理的字节,并保存它们以供稍后处理。

11.2 填充

处理“最坏情况”的另一种方法(不使用流控制或缓冲区)是在转义序列中添加一堆空值(值为零的字节)。有时使用 DEL 代替,前提是它们没有其他功能。请参阅 识别 Del

转义序列启动终端执行某些操作,当终端忙于执行操作时,它会接收到一堆它忽略的空值。当它获得最后一个空值时,它已完成其任务,并准备好执行下一个命令。这称为空填充。这些空值以前称为“填充字符”。添加这些空值只是为了“浪费”时间,但这并非完全浪费,因为终端通常在接收空值时一直忙于执行其他操作。在流控制普及之前,它在过去被广泛使用。为了提高效率,应该添加适量的空值,而弄清楚这一点很乏味。这通常是通过反复试验来完成的,因为终端手册几乎没有或根本没有帮助。如果流控制无法正常工作或未实现,则填充是一种解决方案。stty 命令的某些选项涉及填充。

11.3 串行端口溢出

人们可能想知道串行端口上的溢出是如何发生的,因为数据字节传输中涉及的发送和接收串行端口都设置为相同的速度(以位/秒为单位),例如 19,200。原因是,尽管接收串行端口电子设备可以处理传入的流速,但从串行端口获取和处理字节的硬件/软件有时无法应对高流速。

造成这种情况的一个原因是串行端口的硬件缓冲区非常小。较旧的串行端口的硬件缓冲区大小只有一个字节(在 UART 芯片内部)。如果在下一个字节到达之前没有通过 CPU 指令删除(获取)缓冲区中接收到的一个数据字节,则该字节将丢失(缓冲区溢出)。较新的 UART,即大多数 16550,具有 16 字节的缓冲区(但可以设置为模拟单字节缓冲区),并且不太可能溢出。它可以设置为在其缓冲区中的字节数达到 1、4、8 或 14 字节时发出中断。另一个计算机芯片(通常是计算机的主 CPU 芯片)的工作是从这个小型硬件缓冲区中取出这些传入字节并处理它们(以及执行其他任务)。

当这个小型硬件接收缓冲区的内容达到指定的限制(旧 UART 为一个字节)时,会发出中断。然后,计算机中断它正在执行的操作,软件检查以找出发生了什么。它最终确定需要从串行端口的缓冲区中获取一个或多个字节。它获取这些字节并将它们放入内核在主内存中维护的更大的缓冲区(也是串行端口缓冲区)。对于发送缓冲区,当缓冲区为空(或几乎为空)时,串行硬件会发出中断,以告知 CPU 将更多字节放入其中以发送出去。

终端也有类似于计算机的串行端口和缓冲区。由于到终端的字节流速通常远大于从键盘到主机计算机的反向流速,因此最有可能发生溢出的是终端。当然,如果您使用计算机作为终端(通过仿真),那么它同样容易受到溢出的影响。

更可能发生溢出的风险情况是:1. 当另一个进程禁用了中断时(对于计算机)。2. 当主(或终端)内存中的串行端口缓冲区即将溢出时。

11.4 停止发送

当接收器似乎即将被传入字节淹没时,它会向发送器发送信号以停止发送。这就是流控制,流控制信号始终以与它们控制的数据流相反的方向发送(尽管不在同一通道或线路中)。此信号可以是作为数据线上的普通数据字节发送的控制字符(^S = DC3 = Xoff)(带内信令),也可以是 dtr 到 cts(或其他)信号线中的电压从正到负的转换(带外信令)。使用 Xoff 称为“软件流控制”,在专用信号线(电缆内部)中使用电压转换称为硬件流控制。

11.5 键盘锁定

对于终端,最常见的“停止发送”情况是终端无法跟上发送给它的字符,并且它向 PC 发出“停止”信号。另一个例子是有人按下 control-S。不太常见的情况是 PC 无法跟上您的打字速度,并告诉终端停止发送。终端会“锁定”其键盘,消息或指示灯应告知您这一点。您在锁定的键盘上键入的任何内容都将被忽略。当 PC 完成其工作时,键盘应解锁。当它没有解锁时,很可能出现某种死锁。

另一种类型的键盘锁定发生在向终端发送特定转义序列(或仅适用于 Wyse 60 的 ^O 控制字符)时。虽然前一种类型的锁定是由串行驱动程序完成的,但这种类型的锁定是由真实终端的硬件完成的。如果发生这种情况,这是一个两难境地,因为您无法键入任何命令来摆脱这种锁定。进入设置并重置可能会起作用(但它在我的 Wyse 60 上失败了,我不得不循环供电才能摆脱)。也可以从另一个终端发送“解锁键盘”转义序列。

术语“锁定”有时也用于计算机被告知停止向终端发送的常见情况。键盘未锁定,因此您键入的任何内容都会发送到计算机。由于计算机无法向您发送任何内容,因此您键入的字符不会显示在屏幕上,并且可能看起来键盘已锁定。滚动被锁定(滚动锁定),但键盘未锁定。

11.6 恢复发送

当接收器赶上其处理并准备好接收更多数据字节时,它会向发送器发出信号。对于软件流控制,此信号是控制字符 ^Q = DC1 = Xon,它在常规数据线上发送。对于硬件流控制,信号线中的电压从负(否定)变为正(断言)。如果终端被告知恢复发送,则键盘将被解锁并准备好使用。

11.7 硬件流控制(RTS/CTS 等)

一些较旧的终端没有硬件流控制,而另一些终端则在串行端口上使用了各种不同的引脚来实现此目的。有关各种引脚及其名称的列表,请参阅 标准 Null 调制解调器电缆引脚排列。最常用的引脚似乎是 DTR 引脚(或 DTR 引脚和 DSR 引脚)。

RTS/CTS、DTR 和 DTR/DSR 流控制

Linux PC 使用 RTS/CTS 流控制,但 DTR/DSR 流控制(某些终端使用)的行为类似。DTR 流控制(仅在一个方向上,也由某些终端使用)仅是 DTR/DSR 流控制的 DTR 部分。

RTS/CTS 使用串行 (EIA-232) 连接器上的 RTS 和 CTS 引脚。RTS 表示“请求发送”。当接收器上的此引脚保持断言(正电压)时,表示:继续向我发送数据。如果 RTS 被否定(电压变为负),则否定“请求发送”,这意味着:请求不要向我发送(停止发送)。当接收器准备好接收更多输入时,它会断言 RTS,请求另一端恢复发送。对于计算机和终端(均为 DTE 类型设备),RTS 引脚将流控制信号发送到电缆另一端的 CTS(清除发送)引脚。也就是说,电缆一端的 RTS 引脚连接到另一端的 CTS 引脚。

对于调制解调器(DCE 设备),方案有所不同,因为调制解调器的 RTS 引脚接收信号,而其 CTS 引脚发送信号。虽然这可能看起来令人困惑,但存在有效的历史原因,此处不赘述。

终端通常具有 DTR 或 DTR/DSR 流控制。DTR 流控制与 DTR/DSR 流控制相同,但它是单向的,并且不使用 DSR 引脚。对于终端的 DTR/DSR 流控制,DTR 信号类似于从 RTS 引脚发送的信号,而 DSR 引脚就像 CTS 引脚。

连接 DTR 或 DTR/DSR 流控制

一些终端仅使用 DTR 流控制。这只是单向流控制,以防止终端溢出。它不能保护计算机免受某人打字速度过快而导致计算机无法处理的情况的影响。在标准文件传输串行电缆中,终端的 DTR 引脚连接到计算机的 DSR 引脚。但是 Linux 不支持 DTR/DSR 流控制(尽管某些多端口板的驱动程序可能支持 DTR/DSR 流控制)。解决此问题的一种方法是将终端的 DTR 引脚简单地连接到计算机的 CTS 引脚并设置 RTS/CTS 流控制 (stty crtscts)。只要主机不会被您的打字速度淹没并在试图锁定键盘时放弃 RTS,单向的事实就不会影响任何事情。请参阅 键盘锁定。对于 DTR/DSR 流控制(如果您的终端支持此双向流控制),您可以执行上述操作。但您还需要将终端的 DSR 引脚连接到计算机的 RTS 引脚。这样,如果您打字速度过快,您将受到保护。

旧的 RTS/CTS 握手不同

令人困惑的是,RTS 的原始用途与上述解释几乎相反。原始含义是:我请求发送给您。此请求旨在从终端(或计算机)发送到调制解调器,如果调制解调器决定授予请求,则会从其 CTS 引脚向计算机的 CTS 引脚发送回断言的 CTS:您已清除发送给我。请注意,与现代 RTS/CTS 双向流控制相比,这仅保护一个方向上的流:从计算机(或终端)到调制解调器。

对于较旧的终端,RTS 可能具有此含义,并且当终端有数据要发送时,RTS 会变为高电平。上述用途是流控制的一种形式,因为如果调制解调器希望计算机停止发送,它会丢弃 CTS(连接到计算机的 CTS),并且计算机停止发送。

反向通道

旧的硬拷贝终端可能具有反向通道引脚(例如引脚 19),其行为类似于 RTS/CTS 流控制中的 RTS 引脚。如果纸张或色带用完,此引脚也会被否定。通常可以将此引脚连接到主机计算机的 CTS 引脚。可能有一个拨码开关来设置此信号的极性。

11.8 硬件流控制是由硬件完成的吗?

有些人认为硬件流控制是由硬件完成的,但只有一小部分是由硬件完成的。大部分实际上是由您的操作系统软件完成的。UART 芯片和相关硬件通常根本不了解硬件流控制。当接收到硬件流控制信号时(由于信号线极性翻转),硬件会向 CPU 发出电中断信号。但是,硬件不知道此中断的含义。CPU 停止它正在执行的操作,并跳转到主内存中的一个表,该表告诉 CPU 去哪里找到一个程序,该程序将找出发生了什么并确定如何处理它。在这种情况下,此程序会停止传出的字节流。

但是,即使在这个程序停止流之前,它也已经被中断停止了 CPU 工作的中断停止了。这是硬件流控制更快地停止流的原因之一。它不需要等待程序来完成它。但是,如果该程序没有命令停止流,则一旦该程序退出,流将恢复。因此,即使程序不是第一个实际停止流的程序,该程序对于停止流也是必不可少的。中断发生后,串行端口的硬件发送缓冲区中已有的任何字节(最多 16 个)仍将被发送。因此,即使使用硬件流控制,流也不会立即停止。

使用软件流控制需要检查每个传入字节,以查看它是否是“关闭”字节。这些字节通过 16 字节的接收缓冲区时会延迟。如果“关闭”字节是进入此缓冲区的第一个字节,则可能需要等待接收到另外 15 个字节。然后将读取 16 个字节,并找到“关闭”字节。硬件流控制不会发生这种额外的延迟。

11.9 过时了吗? ETX/ACK 或 ENQ/ACK 流控制

这也是软件流控制,需要了解它的设备驱动程序。字节以数据包形式发送(通过异步串行端口),每个数据包都以 ETX(文本结束)控制字符终止。当终端收到 ETX 时,它会等待直到准备好接收下一个数据包,然后返回 ACK(确认)。当计算机收到 ACK 时,它会发送下一个数据包。等等。Linux 不支持此功能吗?一些 HP 终端使用相同的方案,但使用 ENQ 而不是 ETX。


下一页 上一页 目录