【问题标题】:When are IO completion port packets sent and when not?什么时候发送 IO 完成端口数据包,什么时候不发送?
【发布时间】:2010-06-28 07:49:22
【问题描述】:

我目前正在使用 IO 完成端口开发基于命名管道的 IPC 机制。

不幸的是,我在使用 msdn 文档时遇到了一些问题,因为我不清楚在哪些情况下调用 ReadFile/WriteFile 会导致完成数据包。

当 ERROR_IO_PENDING 返回 FALSE 的情况很清楚,但是当 ERROR_MORE_DATA 返回时显然可能的情况呢?这种情况下会有完成包吗?此外,如果返回其他错误怎么办? 在哪些情况下我必须直接而不是在完成处理程序中处理结果和释放资源?

另一种情况是 ReadFile/WriteFile 甚至成功,这显然也是可能的。 谢天谢地,MSDN 非常清楚 here:

此外,WriteFile 函数有时会返回 TRUE,GetLastError 值为 ERROR_SUCCESS,即使它使用的是异步句柄(也可以返回 FALSE 和 ERROR_IO_PENDING)。 ...在此示例中,建议允许完成端口例程单独负责此类资源的所有释放操作。

此建议是否在所有情况下都正确,而分配给完成端口的句柄的 ReadFile/WriteFile 操作的结果实际上可以(并且应该)完全忽略,因为无论如何都会将数据包发送到端口?

【问题讨论】:

    标签: windows winapi named-pipes overlapped-io io-completion-ports


    【解决方案1】:

    只要 IO 操作能够开始,就会有一个 IO 完成项排队等待 IO 操作。无论IO操作开始后是否遇到错误,都会有一个完成项排队到完成端口。

    IO 系统返回的NTSTATUS 代码与 Win32 错误代码之间存在映射问题,这使得很难区分哪些状态是错误,哪些只是信息。 NTSTATUS,供内核和本机API使用,有四个严重级别:成功、信息、警告和错误。除了错误代码之外的任何内容都表明 IO 操作能够开始。 Win32 只有一种严重性 (ERROR_*),因此必须将成功、信息和警告代码与错误代码一起映射。

    • ERROR_IO_PENDING - STATUS_PENDING 是成功状态
    • ERROR_MORE_DATA - STATUS_BUFFER_OVERFLOW 警告或STATUS_MORE_ENTRIES 成功状态

    您可以忽略 ReadFile 或 WriteFile 返回的任何非错误代码,并期待一个排队的完成项,但确定哪个是哪个可能有点麻烦。如果 Win32 错误代码组织得更好,那就太好了,但 Microsoft 确实提供了从 NTSTATUS 到 Win32 错误代码的映射:http://support.microsoft.com/kb/113996。请参阅平台 SDK 或您的 VS 安装中的 ntstatus.h 以确定 NTSTATUS 代码的严重性。

    当原始 API 调用返回时,可能会完成 IO 操作,例如刚刚从缓存中复制出来的读取请求(无需异步等待)。在这种情况下,为了保持一致性,完成消息仍将排队。

    【讨论】:

      【解决方案2】:
      • 是的,ERROR_MORE_DATA 完全有可能出现在完成数据包中。您应该时刻准备好处理任何潜在的错误。在GetQueuedCompletionStatus 的文档中,很明显当它返回FALSE 时,您应该检查lpOverlapped 参数是否为NULL。如果不是NULL,则I/O完成包有错误。

      • 即使ReadFileWriteFile 返回TRUE,默认行为是完成数据包排队到完成端口。从 Windows Vista 开始,可以更改此策略。请参阅SetFileCompletionNotificationModes 上的文档。

      【讨论】:

        猜你喜欢
        • 2013-09-21
        • 2010-11-18
        • 2012-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-22
        相关资源
        最近更新 更多