导致CreateFile调用串行端口的速度非常慢的原因

What can cause CreateFile calls on a serial port to be extremely slow?

本文关键字:非常 速度 调用 串行端口 导致 CreateFile      更新时间:2023-10-16

我有一个Qt应用程序(Qt 4.8.1),它正在执行一些Windows串行端口任务。我发现偶尔我打开串行端口的CreateFileA调用需要30秒才能完成!很明显,我正在做一些事情来引发这种奇怪的行为,我想知道我可能在做什么来引起这种情况。

m_portHand = CreateFileA( portDevice.c_str(),
                          GENERIC_READ | GENERIC_WRITE,
                          0,      //  must be opened with exclusive-access
                          NULL,   //  default security attributes
                          OPEN_EXISTING, //  must use OPEN_EXISTING
                          FILE_FLAG_OVERLAPPED,      //  overlapped I/O
                          NULL ); //  hTemplate must be NULL for comm devices

m_portHand是一个HANDLE,portDevice是一个std::字符串,包含"COM5"。

这个调用是由我的应用程序主线程中的按钮触发的。在这种情况发生时,应用程序最多有一个其他线程,但这些线程(如果有的话)是空闲的。

系统中唯一的主要功能是运行Linux的虚拟机,但该系统是一个四核系统,其中3个内核几乎处于空闲状态,只有一个内核对虚拟机执行任何操作。

串行端口在一个8端口的USB串行盒上,这可能有关系吗?

这在某种程度上与重叠IO有关吗?

针对评论:

端口未被其他应用打开。此应用程序的上一次调用之前打开了端口,该应用程序已正确关闭,端口使用"CloseHandle"关闭。

我无法确定这需要30秒与否之间的任何相关性——有时我启动应用程序,点击按钮,然后我们就开始比赛了,有时需要30秒。

虚拟机正在拦截同一串行盒上的其他一些USB设备。

除了串行盒(VM轮询4个端口以查找设备)之外,USB总线已卸载。

我没有在其他应用程序中看到这种行为。我会尝试切换到内置端口(主板上的COM1),看看这是否有任何影响。

我突然想到:端口寻址的形式与此有关吗?我使用的其他类似应用程序使用qestserialport库,该库使用'\\打开端口。\COM#’表示法。有没有什么方法可以使所用的符号影响计时?

USB串行设备上显示"VScom",通常它会立即打开(CreateFile调用为<10毫秒)。这只是一个偶尔的问题,事情会被塞满,我有其他程序似乎从来没有表现出这种行为。

与我交谈的设备是一台使用IEEE 11073协议的医疗监护仪。不管怎样,我与设备的连接工作得很好,只是串行端口打开了才有问题。串行控制线在打开时的状态是否与此有关?另一端的设备正在轮询它的端口,寻找各种可以通信的东西,所以我不知道在出现问题的确切时刻串行线是什么样子的。

好的,如果不能解决问题,问题就被理解了。我在玩另一个串行设备,问题开始更加频繁地显现出来。

问题似乎是,当虚拟机控制某些串行端口时,驱动程序打开可用端口的速度会间歇性变慢。

我的测试程序打开然后关闭端口1000次,为打开的调用计时。它不会以任何方式设置串行端口参数。在运行测试程序之前,我正在使用波特率为460800的设备进行实际工作。

当虚拟机拥有其中4个端口时,打开其余4个端口有时可能需要20-30秒(1000次尝试中有20-30次)才能完成。当虚拟机未运行时,所有1000次尝试都会很快打开。由于虚拟机正在运行,但它没有USB串行端口,因此在所有1000次尝试中都会很快打开。

由于虚拟机是一种开发工具,而不是我们预期部署场景的一部分,所以我可以接受这个问题。

有趣的是,这种影响似乎取决于端口上次使用的波特率。在我最初询问之前,我一直在9600波特及以下的波特率下运行,不记得见过这个问题。当我第一次问这个问题时,我正在使用一个115000波特的设备,并且间歇性地出现问题。使用460800波特的最新设备,我经常会遇到问题,以便能够找到问题。不知道为什么,但它就在那里。

与设备驱动程序交互的串行控制线可能是一个原因。

控制信号是否正确连接?

如果没有,请将RTS连接到CTS,并连接CD、DTR和DSR。在DB25上,这意味着连接引脚4和5以及连接引脚6、8和20。在DB9上,连接引脚7和8以及引脚1、4和6。

如果这解决了问题,您应该查找驱动程序设置以忽略打开时的控制信号。