【问题标题】:GetQueuedCompletionStatus - how to identify the “type” of the finished task?GetQueuedCompletionStatus - 如何识别已完成任务的“类型”?
【发布时间】:2021-09-26 00:31:27
【问题描述】:

您能否告诉我,当完成端口队列中出现就绪任务,然后使用 GetQueuedCompletionStatus 函数检索它时,您如何知道该就绪任务是用于读取还是写入?

【问题讨论】:

  • 您可以使用每个操作的OVERLAPPED结构来区分它们。
  • 你会从数据包中得到你传递给 I/O 的指针(如果是 win32 api,这是POVERLAPPED)。基于此,您可以知道您在这个地方保存的所有内容
  • @RbMm,我不知道如何初始化结构 (WSA)OVERLAPPED 的成员,如果每个成员都写了 - 保留供内部使用。
  • @Optimus1 - 但OVERLAPPED 可以是更大结构的一部分,这已经是 - 您自己的结构,您可以在其中存储 I/O 操作类型(读取、写入等)、指向包含您执行 I/O 的文件句柄的对象,指向内存缓冲区的指针等。如果使用本机 api - 这里更容易和清晰 - 您只需将指针(您自己的)传递给 I/O 请求,它保存在内核中(在 IRP 内)并在 I/O 完成时返回给您。 win32层将this指针与指向iosb的指针联合(称为重叠)
  • @Optimus1 - 那又怎样?您在较大的结构中传递指向OVERLAPPED 的指针并将其取回。你可以通过static_cast(如果你继承重叠的形式)或CONTAINING_RECORD(如果你的结构有这个作为成员)来获得你的结构的指针。事实上我所说的 - 和雷米的回答一样

标签: c++ c winapi winsock winsock2


【解决方案1】:

一种常见的方法是编写一个从 Win32 (WSA)OVERLAPPED 结构派生的结构,或者将(WSA)OVERLAPPED 作为其第一个数据成员。然后,您可以将其他数据成员添加到您的结构中,以根据需要识别其任务、跟踪其状态等。

然后,您可以为每个 I/O 操作分配一个结构实例,根据需要填充它,并将指向它的指针作为 (WSA)OVERLAPPED* 指针传递给您选择的 I/O 函数。

当 I/O 完成返回时,您可以将提供的 OVERLAPPED* 指针类型转换为指向您的结构类型的指针以访问其成员。

例如:

enum MY_OP_TYPE { opReading, opWriting };

struct MY_STRUCT : OVERLAPPED // or WSAOVERLAPPED
{
    MY_OP_TYPE opType;
    // other data members as needed...

    MY_STRUCT()
    {
        Internal = 0;
        InternalHigh = 0;
        Offset = 0;
        OffsetHigh = 0;
        hEvent = NULL;
        // other initializations as needed...
    }

    ~MY_STRUCT()
    {
        // cleanups as needed...
        // free hEvent if it is a (WSA)Event object...
    }

    // other methods as needed...
};
MY_STRUCT *ms = new MY_STRUCT;
ms->opType = opReading;
ms->hEvent = ...; // depending on which I/O function you are using, this could be a (WSA)Event object, or a pointer to opaque app data, etc...
// other assignments as needed...
...

if (IoReadingFunction(..., static_cast<OVERLAPPED*>(ms), ...) == FALSE /* or SOCKET_ERROR */)
{
    if (GetLastError() != ERROR_IO_PENDING)
    // or
    // if (WSAGetLastError() != WSA_IO_PENDING) 
    {
        ...
        delete ms;
    }
}
...
OVERLAPPED *ov;
...

GetQueuedCompletionStatus(..., &ov, ... );
if (ov)
{
    MY_STRUCT *ms = static_cast<MY_STRUCT*>(ov);
    // use ms as needed...

    switch (ms->opType)
    {
        ...
    }

    ...

    delete ms;
}

【讨论】:

  • 我无法弄清楚如何初始化结构(WSA)OVERLAPPED的成员,如果每个成员都写了 - 保留供内部使用。
  • 如果使用 C++,您还可以创建一个包含/派生自 OVERLAPPED 的多态类型,并通过枚举跳过类型测试。只需将 LPOVERLAPPED 转换为您的多态类型并调用虚拟 Process() 成员。
猜你喜欢
  • 1970-01-01
  • 2012-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多