OVERLAPPED结构与GetOverlappedResult函数

Overlapped模型深入分析(原理篇)   Overlapped I/O模型深入分析简述:     Overlapped I/O也称Asynchronous  I/O,异步I/O模型。异步I/O和同步I/O不同,同步I/O时,程序被挂起,一直到I/O处理完,程序才能获得控制。异步I/O,调用一个函数告诉OS,进行I/O操作,不等I/O结束就立即返回,继续程序执行,操作系统完成I/O之后,通知消息给你。Overlapped I 阅读详情

异步I/O调用时,我们会用到OVERLAPPED结构和函数GetOverlappedResult。以前一直对GetOverlappedResult比较困惑,这两天看书和代码才知道这个函数的主要作用不过是将Overlapped返回的结果进行一次简单的分析而已。

下面是OVERLAPPED的结构定义:
typedef struct _OVERLAPPED {
    DWORD  Internal;
    DWORD  InternalHigh;
    DWORD  Offset;
    DWORD  OffsetHigh;
    HANDLE hEvent;
} OVERLAPPED;
这个结构中Internal和InternalHigh是两个返回值。写过驱动程序的人知道这两个值对应着irp的IO_STATUS_BLOCK结构:
typedef struct _IO_STATUS_BLOCK {
    union {
        NTSTATUS Status;
        PVOID Pointer;
    };
    ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

其中,Internal就是Status的值;InternalHigh就是Information的值。“Internal”这个单词表明当初MS将这个两个值就是内部使用的。
而普通调用者如何知道其含义呢?
1.当调用返回时(用ReadFile举例):
  若Internal=0时表明返回STATUS_SUCCESS,于是ReadFile返回TRUE,即成功返回;InternalHigh的值保存在lpNumberOfBytesTransferred中。
  若Internal!=0表示出现错误或PENDING,于是ReadFile返回FALSE, GetLastError值就是Internal值。

2.当1中返回ERROR_IO_PENDING时:
这个时候就需要用到GetOverlappedResult了。
  若Internal=0时表明返回STATUS_SUCCESS,于是GetOverlappedResult返回TRUE,即成功返回;InternalHigh的值保存在lpNumberOfBytesTransferred中。
  若Internal!=0表示出现错误,于是GetOverlappedResult返回FALSE, GetLastError值就是Internal值。


附源码:
WINDOWS_2000_SOURCE_CODE\WIN2K\PRIVATE\windows\base\client\error.c

BOOL
WINAPI
GetOverlappedResult(
    HANDLE hFile,
    LPOVERLAPPED lpOverlapped,
    LPDWORD lpNumberOfBytesTransferred,
    BOOL bWait
    )

/*++

Routine Description:

    The GetOverlappedResult function returns the result of the last
    operation that used lpOverlapped and returned ERROR_IO_PENDING.

Arguments:

    hFile - Supplies the open handle to the file that the overlapped
        structure lpOverlapped was supplied to ReadFile, WriteFile,
        ConnectNamedPipe, WaitNamedPipe or TransactNamedPipe.

    lpOverlapped - Points to an OVERLAPPED structure previously supplied to
        ReadFile, WriteFile, ConnectNamedPipe, WaitNamedPipe or
        TransactNamedPipe.
        //这个地址就是当初调用ReadFile是传递的参数的值,一定记住不能错。

    lpNumberOfBytesTransferred - Returns the number of bytes transferred
        by the operation.

    bWait -  A boolean value that affects the behavior when the operation
        is still in progress. If TRUE and the operation is still in progress,
        GetOverlappedResult will wait for the operation to complete before
        returning. If FALSE and the operation is incomplete,
        GetOverlappedResult will return FALSE. In this case the extended
        error information available from the GetLastError function will be
        set to ERROR_IO_INCOMPLETE.
        //若当前还是ERROR_IO_PENDING则判断是否需要无限期的等待。

Return Value:

    TRUE -- The operation was successful, the pipe is in the
        connected state.

    FALSE -- The operation failed. Extended error status is available using
        GetLastError.

--*/

  1.     DWORD WaitReturn; 
  2.  
  3.     // 
  4.     // Did caller specify an event to the original operation or was the 
  5.     // default (file handle) used? 
  6.     // 
  7.  
  8.     if (lpOverlapped->Internal == (DWORD)STATUS_PENDING ) { 
  9.         if ( bWait ) { 
  10.             // 
  11.             //现在还是PENDING,且还需要等待,则无限期等待。 
  12.             //很多人会自己调用WaitForSingleObject后再调用GetOverlappedResult,其实看起来 
  13.             //没多少必要。 
  14.             // 
  15.             WaitReturn = WaitForSingleObject
  16.                             ( lpOverlapped->hEvent != NULL ) ? 
  17.                                 lpOverlapped->hEvent : hFile, 
  18.                             INFINITE 
  19.                             ); 
  20.             } 
  21.         else { 
  22.             WaitReturn = WAIT_TIMEOUT
  23.             } 
  24.  
  25.         if ( WaitReturn == WAIT_TIMEOUT ) { 
  26.             //  !bWait and event in not signalled state 
  27.             SetLastError( ERROR_IO_INCOMPLETE ); 
  28.             return FALSE; 
  29.             } 
  30.  
  31.         if ( WaitReturn != 0 ) { 
  32.              return FALSE;    // WaitForSingleObject calls BaseSetLastError 
  33.              } 
  34.         } 
  35.  
  36.     *lpNumberOfBytesTransferred = (DWORD)lpOverlapped->InternalHigh; 
  37.  
  38.     if ( NT_SUCCESS((NTSTATUS)lpOverlapped->Internal) ){ 
  39.         return TRUE; 
  40.         } 
  41.     else { 
  42.         BaseSetLastNTError( (NTSTATUS)lpOverlapped->Internal ); 
  43.         return FALSE; 
  44.         } 
{
    DWORD WaitReturn;

    //
    // Did caller specify an event to the original operation or was the
    // default (file handle) used?
    //

    if (lpOverlapped->Internal == (DWORD)STATUS_PENDING ) {
        if ( bWait ) {
            //
            //现在还是PENDING,且还需要等待,则无限期等待。
            //很多人会自己调用WaitForSingleObject后再调用GetOverlappedResult,其实看起来
            //没多少必要。
            //
            WaitReturn = WaitForSingleObject(
                            ( lpOverlapped->hEvent != NULL ) ?
                                lpOverlapped->hEvent : hFile,
                            INFINITE
                            );
            }
        else {
            WaitReturn = WAIT_TIMEOUT;
            }

        if ( WaitReturn == WAIT_TIMEOUT ) {
            //  !bWait and event in not signalled state
            SetLastError( ERROR_IO_INCOMPLETE );
            return FALSE;
            }

        if ( WaitReturn != 0 ) {
             return FALSE;    // WaitForSingleObject calls BaseSetLastError
             }
        }

    *lpNumberOfBytesTransferred = (DWORD)lpOverlapped->InternalHigh;

    if ( NT_SUCCESS((NTSTATUS)lpOverlapped->Internal) ){
        return TRUE;
        }
    else {
        BaseSetLastNTError( (NTSTATUS)lpOverlapped->Internal );
        return FALSE;
        }
}


补充:(2009-10-8)

《windows核心编程》(5th版),p293.

---------------

Internal成员:这个成员用来保存已处理的I/O请求的错误码.

InternalHigh成员:当异步I/O请求完成的时候,这个成员用来保存已传输的字节数。

在当初设计OVERLAPPED结构的时候,Microsoft决定不公开Internal和InternalHigh成员(名副其实)。随着时间的推移,Microsoft认识到这些成员包含的信息会对开发人员有用,因此把它们公开了。但是,Microsoft没有改变这些成员的名字,这是因为操作系统的源代码频繁地用到它们,而Microsoft并不想为此修改源代码。

转自:http://hi.baidu.com/calmlier/blog/item/35359dc17add0649b219a86a.html

GetOverlappedResult函数详细解答 GetOverlappedResult GetOverlappedResult函数返回指定文件、指定管道或通信设备上重叠操作的结果。 视窗95:此功能只适用于通讯设备或使用DeviceIoControl功能打开的档案。 BOOL GetOverlappedResult ( HANDLE hFile、//文件、管道或通信设备的句柄 lpoverllapped, //指向重叠结构的指针 LPDWORD... 阅读详情

相关推荐

端口技术 GetOverlappedResult

 早在两年前我就已经能很熟练的运用完成端口这种技术了,只是一直没有机会将它用在什么项目中,这段时间见到这种技术被过分炒作,过分的神秘化,就想写一篇解释它如何工作的文章.想告诉大家它没有传说中的那么高深难懂!有什么错误的地方还请高人指正.转载请注明出处及作者,谢谢!以一个文件传输服务端为例,在我的机器上它只起两个线程就可以为很多个个客户端同时提供文件下载服务,程序的性能会随机器内CPU个数的

thimin的专栏 3345

关于GetOverlappedResult函数的一些知识

之前在写重叠I\O的代码的时候,记得那时是从网络上拷贝的代码例子。在关于重叠操作的等待结果时,一般都是如下的过程: 先 调用waitformultipleobject或waitforsingleobject函数来等待某一个I\O请求绑定的事件对象的激活。等到激活事件对象后,再调用GetOverlappedResult函数取得重叠I\O的结果,这里GetOverlappedResult...

aprfnge03122的博客 530

端口技术 GetOverlappedResult [转]

以一个文件传输服务端为例,在我的机器上它只起两个线程就可以为很多个个客户端同时提供文件下载服务,程序的性能会随机器内CPU个数的增加而线性增长,我尽可能做到使它清晰易懂,虽然程序很小却用到了NT 5的一些新特性,重叠IO,完成端口以及线程池,基于这种模型的服务端程序应该是NT系统上性能最好的了. 首先.做为完成端口的基础,我们应该理解重叠IO,这需要你已经理解了内核对象及操作系统的一些概念概念,

phenixyf的专栏 1075

GetOverlappedResult

异步I/O调用时,我们会用到OVERLAPPED结构函数GetOverlappedResult。以前一直对GetOverlappedResult比较困惑,这两天看书和代码才知道这个函数的主要作用不过是将Overlapped返回的结果进行一次简单的分析而已。 下面是OVERLAPPED结构定义: typedef struct _OVERLAPPED { DWORD Internal;...

thanklife的专栏 2387

串口 OVERLAPPED

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

qq_31089331的博客 721

GetOverlappedResult取操作结果

GetOverlappedResult这个函数的主要作用不过是将Overlapped返回的结果进行一次简单的分析而已。 dwErrorRet = WaitForSingleObject(overlapped.hEvent, milliseconds); if(WAIT_OBJECT_0 == dwErrorRet)//WAIT_OBJECT_0 0x00000000 :指定的对象出有有信号状态 {...

物联网小镇的博客 729

异步机制 - Overlapped

1 前面说到 GetOverlappedResult的bWait含义 GetOverlappedResult的bWait含义表示是否需要等待,如果IO还处于PENDING状态,内部大概实现是这样   hObject = lpOverlapped->hEvent ? lpOverlapped->hEvent : hFile;  WaitStatus = WaitForSingleOb...

weixin_30709809的博客 156

异步读写(ReadFileEx和ReadFile)之overlapped

#include "stdafx.h" #include <windows.h> #include <iostream> using namespace std; #define PAGE_SIZE 0x1000 void Sub_1(); //ReadFile 异步操作 void Sub_2(); //ReadFileEx  DWORD WINAPI Sub_1Thr...

az44yao的专栏 1066

Overlapped I/O

Overlapped I/O是Win32的一项技术,你可以要求操作系统给你传送数据,并且在传送完毕时通知你,这项技术使你的程序在I/O进行过程中仍然能够继续处理事务。 其中I/Ocompletion ports特别显得重要,因为他们是唯一适用于高负载服务器(必须同时维护许多连接线路)的一个技术。 Win32中有三个基本的函数用来执行I/O,他们是CreateFile(),ReadFile(),

jeromeyu的专栏 954

第6章 Overlapped I/O, 在你身后变戏法 ---被激发的 File Handles -3

最简单的 overlapped I/O 类型,是使用它自己的文件 handle 作为同步机制。首先你以 FILE_FLAG_OVERLAPPED 告诉 Win32 说你不要使用默认的同步 I/O。然后,你设立一个 OVERLAPPED 结构,其中内含“I/O 请求”的所有必要参数,并以此识别这个“I/O 请求”,直到它完成为止。接下来,调用 ReadFile() 并以 OVERLAPPED...

weixin_30500105的博客 133
下一篇: arduino bootload 修改及生成
musem2008
博客等级 码龄18年 0粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值