windows - CloseHandle() 在串口实际关闭之前返回

标签 windows winapi serial-port iocp io-completion-ports

我绞尽脑汁想弄清楚串行端口何时完成关闭,以便我可以重新打开它。事实证明,CloseHandle() 在端口实际解锁之前返回。

我正在使用 CreateFile(FILE_FLAG_OVERLAPPED) 打开一个串行端口,使用 CreateIoCompletionPort() 将其与 CompletionPort 相关联,使用 ReadFile( )WriteFile() 并使用 CloseHandle() 关闭它。

我注意到,如果我足够快地关闭并重新打开串行端口,我会从 CreateFile() 返回一个 ERROR_ACCESS_DENIED。尽管我正在等待 CloseHandle() 返回,然后等待与该句柄关联的所有未完成读/写操作从完成端口返回,但这种情况仍在发生。当然有更好的方法:)

如何同步关闭串行端口?请不要重试循环、sleep() 或其他一些廉价的技巧。

编辑:也许这与我使用完成端口和 FILE_FLAG_OVERLAPPED 有关。当读/写操作完成时,我得到一个回调。端口关闭是否有某种回调?

最佳答案

我认为问题出在服务于 COM 端口的驱动程序上。因此 - 将没有 API 来“实际关闭”COM 端口。

顺便说一句,关闭文件句柄后,无需等待所有未完成的 I/O 完成并出现错误。当 CloseHandle 返回时,所有未完成的 I/O 都已经完成/取消,您只需异步接收回调(无论是通过完成端口还是 APC 队列)。

特别是 FTDI 驱动程序(那些模拟 COM->USB 的驱动程序)众所周知是非常有问题的。

我可能只建议在关闭句柄之前尝试刷新数据。您可以等待所有 I/O 完成然后关闭 COM 端口(如果这适用于您的情况)。或者,您可以调用 SetCommMaskWaitCommEvent 以确保没有待处理的发送数据。希望这可能有所帮助。

编辑:

CloseHandle 是否会立即(在返回之前)取消文件句柄上所有未决的 I/O?

严格来说 -

可能还有其他对文件对象的引用。例如,用户模式代码可以调用 DuplicateHandle,或者内核模式驱动程序可以调用 ObReferenceObjectByXXXX。在这种情况下,句柄所指的对象不一定会被释放。

当最后一个句柄关闭时,将调用驱动程序的 DispatchCleanup。它必须根据 this 取消所有未完成的 I/O。 .

然而,当一个线程在 CloseHandle 中时 - 理论上您可以从另一个线程发出另一个 I/O(如果幸运的话 - 句柄仍然有效)。当您调用 I/O 函数(例如 WriteFile 等)时,操作系统会暂时增加对象的引用计数器。这反过来可能会启动另一个 I/O,它不会被 CloseHandle 调用直接取消。

然而在这种情况下,句柄将在发出新的 I/O 后立即被 O/S 关闭,因为对象的引用计数再次达到 0。

因此在这种变态的情况下,可能会发生这样的情况,即在调用 CloseHandle 之后您无法再次重新打开文件。

关于windows - CloseHandle() 在串口实际关闭之前返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8885748/

相关文章:

windows - 在 Powershell 中以系统用户身份运行命令

c - 在 Windows C 中启动一个以毫秒为单位到期的计时器

delphi - 当磁盘可用空间发生变化时如何收到通知?

linux tty端口一打开就自发发送数据

linux - 如何通过SLIP、串口向wifi模块发送命令?

c# - 如何在 C# 中扫描 COM 端口?

c++ - Hook 窗口创建;钩子(Hook)没有被触发

c++ - 在线程错误 C2064 : term does not evaluate to a function taking 0 arguments

delphi - 更改 TCreateParams.WinClassName 是否安全或如何查找另一个自己的应用程序的表单句柄?

c++ - 如何在 C++ win32 API 中使用 pwdlastset 值和 maxpwdage 值获取 pwdexpirydate?