问题描述
我正在尝试为Linux编写一个简单的C串行通信程序.我对阻止/非阻止读取以及VMIN/VTIME关系感到困惑.
I am trying to write a simple C serial communication program for Linux. I am confused about the blocking/non-blocking reads and VMIN/VTIME relationships.
我的问题是,是否应该根据是否有阻塞/非阻塞开放呼叫来设置VMIN/VTIME?
My question is, if I should be settings VMIN/VTIME according to whether I have a blocking/non-blocking open call?
例如,如果我有以下公开通话:
For example, if I have the following open call:
open( "/dev/ttyS0", O_RDWR|O_NONBLOCK|O_NOCTTY)
我应该将VMIN/VTIME设置为:
Should I set the VMIN/VTIME to:
.c_cc[VTIME] = 0;
.c_cc[VMIN] = 0;
,如果我有类似的阻止模式:
and if I have blocking mode like:
open( "/dev/ttyS0", O_RDWR|O_NOCTTY)
我应该将VMIN/VTIME设置为:
should I set the VMIN/VTIME to:
.c_cc[VTIME] = 0;
.c_cc[VMIN] = 1;
?
即使正确设置了端口打开标志,对VMIN/VTIME进行设置也会有所不同吗?
Does it make any difference what VMIN/VTIME are set to even though the port open flags are set appropriately?
如果有人能帮助我了解VMIN/VTIME与阻塞/非阻塞端口之间的关系,我将不胜感激.
If anybody could help me understand the relationship between VMIN/VTIME and blocking/non-blocking ports I would really appreciate it.
谢谢
推荐答案
安德烈是对的.在非阻塞模式下,VMIN/VTIME不起作用(FNDELAY/O_NDELAY似乎是O_NONBLOCK的Linux变体,可移植,带有POSIX标志).
Andrey is right. In non-blocking mode, VMIN/VTIME have no effect (FNDELAY / O_NDELAY seem to be linux variants of O_NONBLOCK, the portable, POSIX flag).
在非阻塞模式下对文件使用select()时,每个到达的字节都会收到一个事件.在高串行数据速率下,这会影响CPU.最好将阻塞模式与VMIN一起使用,以便对于小于VMIN的块,select()在触发事件之前先等待数据块,并使用VTIME来限制延迟.
When using select() with a file in non-blocking mode, you get an event for every byte that arrives. At high serial data rates, this hammers the CPU. It's better to use blocking mode with VMIN, so that select() waits for a block of data before firing an event, and VTIME to limit the delay, for blocks smaller than VMIN.
Sam说:如果要确保每半秒获取一次数据,则可以设置vtime"(VTIME = 5).
Sam said "If you want to make sure you get data every half second you could set vtime" (VTIME = 5).
直觉上,您可能希望这是对的,但事实并非如此. BSD termios手册页比Linux更好地解释了它(尽管它们都以相同的方式工作). VTIME计时器是一个 interbyte 计时器.从每个新字节到达串行端口开始.在最坏的情况下,select()最多可能需要等待20秒才能触发事件.
Intuitively, you may expect that to be true, but it's not. The BSD termios man page explains it better than linux (though they both work the same way). The VTIME timer is an interbyte timer. It starts over with each new byte arriving at the serial port. In a worst case scenario, select() can wait up to 20 seconds before firing an event.
假设您的VMIN = 250,VTIME = 1,串行端口的速率为115200 bps.另外,假设您有一个连接的设备以9 cps的恒定速率缓慢发送单个字节.字节之间的时间为0.11秒,足够长以使0.10的字节间计时器到期,并且select()报告每个字节的可读事件.一切都很好.
Suppose you have VMIN = 250, VTIME = 1, and serial port at 115200 bps. Also suppose you have an attached device sending single bytes slowly, at a consistent rate of 9 cps. The time between bytes is 0.11 seconds, long enough for the interbyte timer of 0.10 to expire, and select() to report a readable event for each byte. All is well.
现在,假设您的设备将其输出速率提高到11 cps.字节之间的时间为0.09秒.字节间计时器到期的时间不够长,每个新字节都会重新开始.为了获得可读的事件,必须满足VMIN = 250.以11 cps的速度耗时22.7秒.您的设备似乎停滞了,但是VTIME设计是造成延迟的真正原因.
Now suppose your device increases its output rate to 11 cps. The time between bytes is 0.09 seconds. It's not long enough for the interbyte timer to expire, and with each new byte, it starts over. To get a readable event, VMIN = 250 must be satisfied. At 11 cps, that takes 22.7 seconds. It may seem that your device has stalled, but the VTIME design is the real cause of delay.
我用两个Perl脚本(发送者和接收者),两个端口的串行卡和一根无效的调制解调器电缆进行了测试.我证明了它可以按照手册页中的说明进行工作. VTIME是一个字节间计时器,随着每个新字节的到来而重置.
I tested this with two Perl scripts, sender and receiver, a two port serial card, and a null modem cable. I proved that it works as the man page says. VTIME is an interbyte timer that's reset with the arrival of each new byte.
更好的设计是固定计时器,而不是滚动计时器.它会继续滴答直到到期,或满足VMIN(以先到者为准).现有的设计可能是固定的,但是有30多年的遗产需要克服.
A better design would have the timer anchored, not rolling. It would continue ticking until it expires, or VMIN is satisfied, whichever comes first. The existing design could be fixed, but there is 30 years of legacy to overcome.
在实践中,您可能很少遇到这种情况.但是它潜伏着,所以要当心.
In practice, you may rarely encounter such a scenario. But it lurks, so beware.
这篇关于termios VMIN VTIME和阻塞/非阻塞读取操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!