3

我有一个使用 boost asio 打开串行端口的程序。

默认情况下,串行端口具有保持线路空闲的延迟。在 Windows 平台上,我看到了 30 毫秒的延迟,而在 Linux 平台上,延迟是 20 毫秒。

对于 Linux 环境,我发现“linux.h”的“ioctl”类有一种方法可以使用一些标志(以及我需要的:low_latency)来设置串行设置。

代码如下:

boost::asio::basic_serial_port<boost::asio::serial_port_service>::native_type native = serial_port_.native(); // serial_port_ is the boost's serial port class.
struct serial_struct serial;
ioctl(native, TIOCGSERIAL, &serial);
serial.flags |= ASYNC_LOW_LATENCY; // (0x2000)
ioctl(native, TIOCSSERIAL, &serial);

我也想减少我的 Windows 平台上的延迟。是否有一种等效的方法可以对带有 C++ 的 Windows 执行相同的操作?

顺便说一句,我看到有一些解决方案建议在 Windows 设备管理器中更改串行端口的属性,但我没有这些解决方案显示的这些属性,我需要一个代码解决方案。

4

2 回答 2

2

从 windows 中的 boost asio 获取本机句柄并将其传递给 SetCommTimeouts: http: //msdn.microsoft.com/en-us/library/windows/desktop/aa363437 (v=vs.85).aspx

特别是看COMMTIMEOUT结构的ReadIntervalTimeout:http: //msdn.microsoft.com/en-us/library/windows/desktop/aa363190 (v=vs.85).aspx

ReadIntervalTimeout 两个字节到达通信线路之间允许经过的最长时间,以毫秒为单位。在 ReadFile 操作期间,时间段从接收到第一个字节开始。如果任意两个字节到达的时间间隔超过此数量,则 ReadFile 操作完成并返回任何缓冲数据。零值表示不使用间隔超时。MAXDWORD 值与 ReadTotalTimeoutConstant 和 ReadTotalTimeoutMultiplier 成员的零值相结合,指定读取操作将立即返回已收到的字节,即使没有收到任何字节。

您还可以使用 GetCommTimeouts 查询当前值:http: //msdn.microsoft.com/en-us/library/windows/desktop/aa363261 (v=vs.85).aspx

于 2012-08-14T05:58:05.637 回答
0

我记得在 NT4/Win2k/WinXP 时代遇到过这个问题,我想你遇到的问题是相似的。

使用 COMMTIMEOUT 结构总是在每次超时后添加时间片延迟,这意味着对于可变长度数据包,您总是添加 10 毫秒或 16 毫秒的延迟,具体取决于机器是否为 SMP 机器。例如,您无法真正获得 1 毫秒的超时。即使在具有完成端口的串行端口上的异步操作上使用 COMMTIMEOUT 也是如此。

为了消除这个问题,我使用了 IO Completion Ports 并且有一个单字符读取操作的管道未完成。当字节到达端口时读取完成,并且可以在主 IOCP 事件循环中出列。这以一些代码复杂性为代价提供了非常高的性能。

这种方法不适用于 boost::asio,因为只允许一个未完成的读取。您可以尝试为 Windows for asio 实现基于 Windows IOCP 的串行端口后端,或者您可以为串行通信使用单独的 IOCP 和线程。

于 2012-08-16T23:23:21.220 回答