none
C语言怎么用OVERLAPPED进行重叠IO操作? RRS feed

  • 问题

  • OVERLAPPED结构的定义为

    typedef struct _OVERLAPPED {
      ULONG_PTR Internal;
      ULONG_PTR InternalHigh;
      union {
        struct {
          DWORD Offset;
          DWORD OffsetHigh;
        };
        PVOID  Pointer;
      };
      HANDLE    hEvent;
    } OVERLAPPED, *LPOVERLAPPED;
    

    MSDN中,Internal、InternalHigh、Pointer均标记为“Reserved for system use”,hEvent只能是0或者CreateEvent创建的合法的Event。那么问题来了,C语言没有继承,GetQueuedCompletionStatus函数得到OVERLAPPED指针后,怎么获取关联的数据?

    举个例子

    char buffer[4 * 1024];
    {
    	HANDLE hFile = CreateFileW(L"d:\1.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    	OVERLAPPED* op = (OVERLAPPED*)malloc(sizeof(OVERLAPPED));
    	ReadFileEx(hFile, buffer, sizeof(buffer), op, NULL);
    }
    {
    	DWORD dwNumberOfBytes = 0;
    	ULONG_PTR key = 0;
    	OVERLAPPED* op = NULL;
    	GetQueuedCompletionStatus(hCompletionPort, &dwNumberOfBytes, &key, &op, INFINITE);
    }
    异步读操作完成,并在GetQueuedCompletionStatus处得到OVERLAPPED*,怎么知道读取的是哪个文件的内容呢?

    2017年4月18日 13:32

答案

  • Hi 潇羽,

    感谢在MSDN论坛发帖。

    >>异步读操作完成,并在GetQueuedCompletionStatus处得到OVERLAPPED*,怎么知道读取的是哪个文件的内容呢?

    当你使用CreateIoCompletionPort函数创建I/O completion port的时候,你会输入一个CompletionKey。 这是一个用户定义的, 对应每个文件句柄的完成密钥。 包含在指定文件句柄的每个I / O完成数据包中。

    使用CompletionKey参数可以帮助你的应用程序跟踪哪些I / O操作已经完成。该值不被CreateIoCompletionPort用于功能控制;而是在与I / O完成端口关联时附加到FileHandle参数中指定的文件句柄。这个完成密钥对于每个文件句柄应该是唯一的,并且它在整个内部完成排队过程中伴随文件句柄。当完成数据包到达时,它在GetQueuedCompletionStatus函数调用中返回。

    希望对你有所帮助。

    Best Regards,

    Sera Yu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • 已建议为答案 Baron Bi 2017年4月21日 2:05
    • 已标记为答案 潇羽 2017年4月27日 1:49
    2017年4月20日 6:51
  • >>CompletionKey这个参数,只有用户调用PostQueuedCompletionStatus函数才能自定义CompletionKey值,操作系统完成异步调用,GetQueuedCompletionStatus函数得到的CompletionKey值,就是调用CreateIoCompletionPort函数时写好的CompletionKey值,无法改变。

    正是因为CompletionKey的值是唯一的,不会改变的,所以可以使用CompletionKey参数来帮助应用程序跟踪哪些I / O操作已经完成。 每一个FileHandle都对应一个CompletionKey。通过这个CompletionKey就可以找到相应的文件句柄。然后通过文件句柄获取相关参数。

    希望对你有所帮助。

    Best Regards,
    Sera Yu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • 已标记为答案 潇羽 2017年4月27日 1:49
    2017年4月26日 9:12

全部回复

  • Hi 潇羽,

    感谢在MSDN论坛发帖。

    >>异步读操作完成,并在GetQueuedCompletionStatus处得到OVERLAPPED*,怎么知道读取的是哪个文件的内容呢?

    当你使用CreateIoCompletionPort函数创建I/O completion port的时候,你会输入一个CompletionKey。 这是一个用户定义的, 对应每个文件句柄的完成密钥。 包含在指定文件句柄的每个I / O完成数据包中。

    使用CompletionKey参数可以帮助你的应用程序跟踪哪些I / O操作已经完成。该值不被CreateIoCompletionPort用于功能控制;而是在与I / O完成端口关联时附加到FileHandle参数中指定的文件句柄。这个完成密钥对于每个文件句柄应该是唯一的,并且它在整个内部完成排队过程中伴随文件句柄。当完成数据包到达时,它在GetQueuedCompletionStatus函数调用中返回。

    希望对你有所帮助。

    Best Regards,

    Sera Yu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • 已建议为答案 Baron Bi 2017年4月21日 2:05
    • 已标记为答案 潇羽 2017年4月27日 1:49
    2017年4月20日 6:51
  • 感谢您的回答

    CompletionKey这个参数,只有用户调用PostQueuedCompletionStatus函数才能自定义CompletionKey值,操作系统完成异步调用,GetQueuedCompletionStatus函数得到的CompletionKey值,就是调用CreateIoCompletionPort函数时写好的CompletionKey值,无法改变。

    所以,没办法用CompletionKey得到用户自定义参数啊。

    2017年4月25日 8:53
  • >>CompletionKey这个参数,只有用户调用PostQueuedCompletionStatus函数才能自定义CompletionKey值,操作系统完成异步调用,GetQueuedCompletionStatus函数得到的CompletionKey值,就是调用CreateIoCompletionPort函数时写好的CompletionKey值,无法改变。

    正是因为CompletionKey的值是唯一的,不会改变的,所以可以使用CompletionKey参数来帮助应用程序跟踪哪些I / O操作已经完成。 每一个FileHandle都对应一个CompletionKey。通过这个CompletionKey就可以找到相应的文件句柄。然后通过文件句柄获取相关参数。

    希望对你有所帮助。

    Best Regards,
    Sera Yu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • 已标记为答案 潇羽 2017年4月27日 1:49
    2017年4月26日 9:12