在 C 中获取 Windows 串行端口的输入缓冲区长度

Getting input buffer length for Windows serial port in C

是否有非阻塞函数returns Windows 中串行端口的当前 rx 队列长度,使用 C?

我见过的所有示例都简单地调用了 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);

要通过 ReadFile 使用 COM 端口执行异步 IO,请考虑使用函数的最后一个参数,LPOVERLAPPEDOVERLAPPED 结构。 OVERLAPPED 是 Windows 中异步 IO 的常见做法。

Here you can find examples

ReadFile 将始终 return rx 缓冲区中已有的任何内容。因此,如果您不设置超时,您将立即获得内容。

不过请注意,没有专业应用程序会将 ReadFile 置于忙等待循环中。这不仅会不必要地耗尽 CPU,还会阻塞存在循环的线程。

所以你应该把 ReadFile 放在它自己的线程中。这是所有 I/O 函数的常见做法。这将解决阻塞问题,但您仍然会遇到 CPU 使用率高的问题。

作为替代方案,您可以使用 Windows 调用 "asynchronous I/O" (*) 的方法,方法是使用 ReadFileEx 函数。它允许您指定一个回调函数,只要您实际收到一些数据就会触发该函数。

现在,如果您将 "asynchronous I/O" 与线程结合使用,您将获得一种非阻塞通信,当没有要处理的数据时,它不会消耗 CPU。您的 I/O 线程可以使用 SleepEx 等待 I/O,也可以等待您从回调内部手动设置的事件。


(*) "Asynchronous I/O" 是无意义的 Windows 术语,因为从技术上讲,所有串行端口通信始终是异步的。如果您不间断地同步发送数据,速度较慢的台式 PC 将无法跟上。