在 C 中获取 Windows 串行端口的输入缓冲区长度
Posted
技术标签:
【中文标题】在 C 中获取 Windows 串行端口的输入缓冲区长度【英文标题】:Getting input buffer length for Windows serial port in C 【发布时间】:2016-06-14 08:40:02 【问题描述】:是否有一个非阻塞函数可以在 Windows 中使用 C 返回串行端口的当前 rx 队列长度?
我见过的所有示例都只是调用ReadFile
,它会阻塞直到指定的超时,所以我想知道是否可以在读取之前检查缓冲区中是否有任何内容?
例如我可以简单地为每个角色执行此操作:
void ReadCharacter(char *theCharacter)
DWORD numBytesRead = 0;
while (numBytesRead == 0)
ReadFile(comPorthandle,
theCharacter,
sizeof(char),
&numBytesRead,
NULL);
但是有没有可能有类似的东西
int numBytesRx = GetNumBytesRx(&portHandle);
if (numBytesRx > 0)
Read(&portHandle, targetBuffer, numBytesRead);
【问题讨论】:
你可以使用timeouts 【参考方案1】:要通过ReadFile
与 COM 端口执行异步 IO,请考虑使用函数的最后一个参数 LPOVERLAPPED
和 OVERLAPPED
结构。 OVERLAPPED
是 Windows 中异步 IO 的常见做法。
Here you can find examples
【讨论】:
ReadFileEx
,如果你想回调的话。
@Lundin 这只是另一种做事方式。我不会说这更容易,因为当你想接收回调时,你需要你的线程在警报状态下等待,并且你需要一个单独的过程。
在进行任何形式的 I/O 时,您应该始终拥有一个单独的线程。是的,它往往会变得有点复杂。【参考方案2】:
ReadFile
将始终返回 rx 缓冲区中已有的内容。因此,如果您不设置超时,您将立即获得内容。
请注意,没有专业应用程序会将ReadFile
置于忙等待循环中。这不仅会不必要地占用 CPU,还会阻塞存在循环的线程。
所以你应该把ReadFile
放在它自己的线程中。这是所有 I/O 功能的常见做法。这将解决阻塞问题,但您仍然会遇到 CPU 使用率高的问题。
作为替代方案,您可以通过ReadFileEx
函数使用Windows 所谓的“异步I/O”(*)。它允许您指定一个回调函数,当您实际接收到一些数据时将触发该函数。
现在,如果您将“异步 I/O”与线程相结合,您将获得非阻塞通信,当没有数据要处理时,它不会消耗 CPU。您的 I/O 线程可以使用 SleepEx
等待 I/O,也可以 WaitFor 您在回调内部手动设置的事件。
(*) “异步 I/O”是一个无意义的 Windows 术语,因为从技术上讲,所有串行端口通信始终是异步的。您是否会同步发送数据而没有中间停顿,那么速度较慢的台式 PC 将无法跟上。
【讨论】:
异步 I/O 从程序员的角度来看是异步的,也就是说,数据传入或传出程序员提供的缓冲区是异步发生的。它与硬件在做什么无关! @HarryJohnston 当然它与硬件有关,因为字节出现在缓冲区中作为硬件指示。同步/异步通信是明确定义的技术术语。不要陷入听微软的陷阱,因为他们试图将世界上每一个行业事实上的标准术语重新命名为其他名称。 @Lundin:嗯,我不确定他们是否应该用不同的名称来命名它,但我认为从 API 的角度来看这并不模棱两可。ReadFile
阻塞了一个本质上的异步操作,而 ReadFileEx
没有阻塞,这一事实在进入低级别时绝对是一件好事。但我不明白为什么如果ReadFileEx
只是产生一个后台线程并在后台读取一个阻塞方法,它会对 my 代码产生什么影响?
@LousyCoder ReadFileEx 不会产生线程,它只是在有数据要读取时执行回调函数。我只是建议您将所有 I/O 放在一个单独的线程中,因为这样可以为您提供良好的程序设计。
@Lundin:是的,我写的(也许我不清楚)是,从 API 的角度来看,它 不 生成线程是无关紧要的。 ReadFile
是阻止本质上异步操作的那个。以上是关于在 C 中获取 Windows 串行端口的输入缓冲区长度的主要内容,如果未能解决你的问题,请参考以下文章
Windows 串行:在接收到起始字节之前丢弃输入缓冲区中接收到的所有字节
检索用户空间 Linux C 代码中 USB 串行写入传输的缓冲区/数据包/有效负载大小