我正在尝试为Linux编写一个简单的C串行通信程序.我对阻塞/非阻塞读取和VMIN / VTIME关系感到困惑.我的问题是,如果我应该根据我是否有阻止/非阻塞打开呼叫来设置VMIN / VTIME?例如,如果我有以下打开电话:open( /...
我正在尝试为Linux编写一个简单的C串行通信程序.我对阻塞/非阻塞读取和VMIN / VTIME关系感到困惑.
我的问题是,如果我应该根据我是否有阻止/非阻塞打开呼叫来设置VMIN / VTIME?
例如,如果我有以下打开电话:
open( "/dev/ttyS0", O_RDWR|O_NONBLOCK|O_NOCTTY)
我应该将VMIN / VTIME设置为:
.c_cc[VTIME] = 0;
.c_cc[VMIN] = 0;
如果我有阻止模式,如:
open( "/dev/ttyS0", O_RDWR|O_NOCTTY)
我应该将VMIN / VTIME设置为:
.c_cc[VTIME] = 0;
.c_cc[VMIN] = 1;
?
即使端口打开标志设置正确,VMIN / VTIME设置为什么也没有任何区别?
如果有人能帮助我理解VMIN / VTIME与阻塞/非阻塞端口之间的关系,我将非常感激.
谢谢
解决方法:
安德烈是对的.在非阻塞模式下,VMIN / VTIME无效(FNDELAY / O_NDELAY似乎是O_NONBLOCK的linux变体,便携式,POSIX标志).
将select()与非阻塞模式的文件一起使用时,会为每个到达的字节获取一个事件.在高串行数据速率下,这会破坏CPU.最好在VMIN中使用阻塞模式,以便select()在触发事件之前等待数据块,而VTIME用于限制小于VMIN的块的延迟.
Sam说:“如果你想确保每半秒获得一次数据就可以设置vtime”(VTIME = 5).
直觉上,你可能会认为这是真的,但事实并非如此. BSD termios手册页比linux更好地解释了它(尽管它们的工作方式相同). VTIME定时器是一个间歇定时器.它从每个新字节到达串行端口开始.在最坏的情况下,select()可以在触发事件之前等待最多20秒.
假设您有VMIN = 250,VTIME = 1和串行端口为115200 bps.还假设您有一个连接设备缓慢发送单个字节,以9 cps的一致速率.字节之间的时间为0.11秒,足以使0.10的字节间定时器到期,而select()则报告每个字节的可读事件.一切都很好.
现在假设您的设备将其输出速率提高到11 cps.字节之间的时间是0.09秒.它不足以让间歇计时器到期,并且每个新字节都会重新开始.要获得可读事件,必须满足VMIN = 250.在11 cps,这需要22.7秒.您的设备似乎已停滞不前,但VTIME设计是导致延迟的真正原因.
我使用两个Perl脚本,发送器和接收器,双端口串行卡和零调制解调器电缆对此进行了测试.我证明了它的工作原理正如man page所说的那样. VTIME是一个间歇定时器,随着每个新字节的到来而复位.
更好的设计会使计时器锚定,而不是滚动.它将继续滴答,直到它到期,或VMIN满意,以先到者为准.现有设计可以修复,但需要克服30年的遗产.
在实践中,您可能很少遇到这种情况.但它潜伏着,所以要小心.
本文标题为:linux – termios VMIN VTIME和阻塞/非阻塞读取操作
基础教程推荐
- iOS Crash常规跟踪方法及Bugly集成运用详细介绍 2023-01-18
- iOS中如何判断当前网络环境是2G/3G/4G/5G/WiFi 2023-06-18
- MVVMLight项目Model View结构及全局视图模型注入器 2023-05-07
- Android开发Compose集成高德地图实例 2023-06-15
- IOS获取系统相册中照片的示例代码 2023-01-03
- Flutter进阶之实现动画效果(三) 2022-10-28
- iOS开发使用XML解析网络数据 2022-11-12
- Android Compose自定义TextField实现自定义的输入框 2023-05-13
- iOS开发 全机型适配解决方法 2023-01-14
- Android实现短信验证码输入框 2023-04-29