IO完成端口密钥混乱 [英] IO completion port key confusion

查看:93
本文介绍了IO完成端口密钥混乱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写基于IO完成端口的服务器(此处的源代码),并使用ctypes模块在Python中使用Windows DLL API。但这是API的直接用法,这个问题是针对那些了解IOCP的人,而不是Python。

I'm writing an IO completion port based server (source code here) using the Windows DLL API in Python using the ctypes module. But this is a pretty direct usage of the API and this question is directed at those who have a knowledge of IOCP, not Python.

据我所知,CreateIoCompletionPort文档是,当您使用文件句柄(在本例中为套接字)调用此函数时,您将指定用户定义完成键,您将其与创建的IOCP关联。当您遍历调用GetQueuedCompletionStatus时,您将获得完成键值以及指向重叠对象的指针。完成密钥应标识哪些重叠对象和请求已完成。

As I understand the documentation for CreateIoCompletionPort, you specify your "user defined" completion key when you call this function with a file handle (in my case a socket) you are associating with the created IOCP. When you get around to calling GetQueuedCompletionStatus, you get a completion key value along with a pointer to an overlapped object. The completion key should identify what overlapped object and request has completed.

但是,假设我在CreateIoCompletionPort调用中传入了100作为重叠对象,作为完成密钥。当相同的重叠对象的IO完成并且通过GetQueuedCompletionStatus返回时,它所伴随的完成密钥就更大了,与原始值100几乎没有相似之处。

However, let's say I pass in 100 as the completion key in my CreateIoCompletionPort call with an overlapped object. When the same overlapped object has its IO completed and it arrives back through GetQueuedCompletionStatus, the completion key that accompanies it is much larger and bares no resemblance to the original value of 100.

我是误解了完成密钥是如何工作的,还是在上面链接的源代码中我做错了吗?

Am I misunderstanding how the completion key works, or must I be doing it wrong in the source code I linked above?

推荐答案

我在日常练习中发现,最好只关注 OVERLAPPED 结果,因为结果不变。有效使用它的一种方法是具有以下内容:

What I've found in everyday practice is that it is best to simply focus on the OVERLAPPED result, as that will be unchanged. One way that you can use it effectively is to have something like the following:

struct CompletionHandler
{
    OVERLAPPED dummy_ovl;
    /* Stuff that actually means something to you here */
};

当您将某些内容发布到IOCP时(无论是通过I / O调用还是通过Win32 API发布) ),您首先创建一个用于跟踪调用的 CompletionHandler 对象,然后将该对象的地址强制转换为 OVERLAPPED *

When you post something to the IOCP (whether via I/O call or just a post via Win32 API), you first create a CompletionHandler object that you will use to track the call, and cast the address of that object to OVERLAPPED*.

CompletionHander my_handler;
// Fill in whatever you need to in my_handler
// Don't forget to keep the original my_handler!

// I/O call goes here, and for OVERLAPPED* give: (OVERLAPPED*)&my_handler

这样,当您得到重叠结果时,您所要做的就是将其转换回 CompletionHandler ,瞧!您具有通话的原始上下文。

This way, when you get the OVERLAPPED result all you have to do is cast it back to CompletionHandler and voila! You have the original context of your call.

OVERLAPPED* from_queued_completion_status;
// Actually get a value into from_queued_completion_status

CompletionHandler* handler_for_this_completion = (CompletionHandler*)from_queued_completion_status;
// Have fun!

有关实际设置的更多详细信息,请查看Boost的ASIO for Windows实施(此处为1.42标头)。有一些细节,例如验证您从 GetQueuedCompletionStatus 获得的 OVERLAPPED 指针,但是同样,请参见链接以获取一种好的方法实施。

For more details in a real-world setting, check out Boost's implementation of ASIO for Windows (ver 1.42 header here). There are some details like validation the OVERLAPPED pointer you get from GetQueuedCompletionStatus, but again, see the link for a good way to implement.

这篇关于IO完成端口密钥混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆