我目前正在使用IO完成端口基于命名管道的IPC机制。
不幸的是我在msdn文档中遇到了一些麻烦,因为我很不清楚在哪种情况下调用ReadFile / WriteFile会导致完成数据包。
使用ERROR_IO_PENDING返回FALSE的情况很明显,但是当返回ERROR_MORE_DATA时,显然可能的情况呢?在这种情况下是否会有完成包?而且,如果返回其他错误怎么办? 在哪些情况下我必须直接处理结果并释放资源而不是在完成处理程序中?
另一种情况是,如果ReadFile / WriteFile成功,显然也是可能的。 值得庆幸的是MSDN非常明确here:
此外,WriteFile函数有时会返回TRUE,其GetLastError值为ERROR_SUCCESS,即使它使用的是异步句柄(也可以使用ERROR_IO_PENDING返回FALSE)。 ...在此示例中,建议允许完成端口例程单独负责此类资源的所有释放操作。
这个建议在所有情况下都是正确的吗?分配给完成端口的句柄的ReadFile / WriteFile操作的结果实际上(并且应该)完全被忽略,因为数据包仍然被发送到端口?
答案 0 :(得分:3)
只要IO操作能够启动,就会有一个IO完成项排队等待IO操作。无论IO操作开始后是否遇到错误,完成项都将排队到完成端口。
IO系统返回的NTSTATUS
代码与Win32错误代码之间存在映射问题,这使得很难判断哪些状态是错误,哪些只是信息。内核和本机API使用的NTSTATUS
有四个级别的严重性:成功,信息,警告和错误。除了错误代码之外的任何内容都表明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操作,例如,刚刚从缓存中复制的读取请求(无需异步等待)。在这种情况下,为了保持一致性,完成消息仍将排队。
答案 1 :(得分:1)
是的,ERROR_MORE_DATA
完全有可能出现在完成包中。您应始终准备好处理任何潜在的错误。在GetQueuedCompletionStatus
的文档中,很明显当它返回FALSE
时,您应该检查lpOverlapped
参数是否为NULL
。如果它不是NULL
,则I / O完成数据包包含错误。
默认行为是即使ReadFile
或WriteFile
返回TRUE
,完成数据包也会排队到完成端口。从Windows Vista开始,可以更改此策略。请参阅SetFileCompletionNotificationModes
上的文档。