IO 完成端口和重叠管理
Posted
技术标签:
【中文标题】IO 完成端口和重叠管理【英文标题】:IO Completion Ports and OVERLAPPED management 【发布时间】:2013-08-14 12:40:01 【问题描述】:win32 如何在两个函数的上下文中管理 OVERLAPPED 结构的实例:
GetQueuedCompletionStatus
PostQueuedCompletionStatus
当我调用 GetQueuedCompletionStatus 时,WIN32 免费实例是 OVERLAPPED 结构还是我必须自己做?
当我使用 PostQueuedCompletionStatus 发送数据时,win32 是否会将其复制到内部结构?何时必须释放已发送数据的内存?
在哪里可以找到一些在 GetQueuedCompletionStatus、PostQueuedCompletionStatus 和 IOCP 队列之间处理重叠数据的方案的图片?
【问题讨论】:
【参考方案1】:OVERLAPPED
结构必须存在,从成功执行 I/O 操作(或手动 PostQueuedCompletionStatus())到调用 GetQueuedCompletionStatus() 出现 OVERLAPPED
。
您对结构的生命周期负责。
您将从 MSDN 文档中看到 GetQueuedCompletionStatus()
实际上采用“一个指向变量的指针,该变量接收在启动完成的 I/O 操作时指定的 OVERLAPPED
结构的地址。”。您实际上从该调用中得到的是一个指向您在进行 PostQueuedCompletionStatus()
调用(或启动重叠 I/O 操作)时传递的原始 OVERLAPPED
的指针。
这实际上非常有用,因为使用 OVERLAPPED
结构的“正常”方式是将其放置在一个更大的结构中,该结构包含您可能需要的所有“每次操作”信息 - 所以这是理想的方式直接从您在调用 GetQueuedCompletionStatus()
时获得的有限信息导航到您在重叠读取调用中使用的数据缓冲区...
我发现处理OVERLAPPED
结构的最佳方法是 a) 将它们嵌入到用于读/写的缓冲区中 b) 对它们进行引用计数和 c) 在引用时将它们返回到池中以供重用计数降至 0。
我有一些你可以下载的源代码 (here),这可能会让这更容易理解(这是一个完整的 IOCP 服务器示例,所以它有点复杂,但它可以工作并展示了如何使用这些东西)。
【讨论】:
Len 请告诉我是否调用 PostQueuedCompletionStatus() 是由操作系统而不是由我进行的,那么我必须在 GetQueuedCompletionStatus() 之后释放收到的数据吗?或者在这种情况下我不是它的所有者?通过调用操作系统,我的意思是例如可以是文件已更改的消息。 调用 GetQueuedCompletionStatus() 产生的所有OVERLAPPED
结构在某个时候最初归您所有。您将调用一个函数,例如WSARecv()
或ReadDirectoryChangesW()
,并传入OVERLAPPED
。没有任何情况(据我所知)您可以调用 API 导致使用最初不是由您提供的 OVERLAPPED
完成。【参考方案2】:
-
您应该将
OVERLAPPED *
的地址传递给GetQueuedCompletionStatus
。这将填充传递给PostQueuedCompletionStatus
的值。
您不应在PostQueuedCompletionStatus
上下文中释放此数据。它应该通过使用GetQueuedCompletionStatus
的上下文来完成。 (假设它首先是动态分配的 - 不需要它是动态分配的结构,它可以从固定池中取出,或者分配在一个函数的堆栈上,直到它有已发出操作完成的信号)。
我不确定是否有这样的图片。
【讨论】:
垫子谢谢!据我了解,默认情况下,我必须只释放我自己的数据(我由 PostQueuedCompletionStatus 发送)并且只能在 GetQueuedCompletionStatus 之后释放?以上是关于IO 完成端口和重叠管理的主要内容,如果未能解决你的问题,请参考以下文章