OVERLAPPED结构与GetOverlappedResult函数

异步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.

--*/

[html] view plain copy

print?

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

补充:(2009-10-8)

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

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

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

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

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

-------

由于Microsoft公开了这些成员,所以我们看到并不一定需要GetOverLappedResult了。:)

时间: 2024-08-26 05:42:20

OVERLAPPED结构与GetOverlappedResult函数的相关文章

异步IO模型和Overlapped结构

.NET中的 Overlapped 类 异步IO模型和Overlapped结构(http://blog.itpub.net/25897606/viewspace-705867/) 数据结构 OVERLAPPED结构主要用于异步I/O操作,其数据结构定义如下: typedef struct _OVERLAPPED {     DWORD Internal;     // 系统保留,存放系统设置的状态     DWORD InternalHigh; // 系统保留,存放被传输数据的长度     DW

OVERLAPPED 结构

typedef struct _OVERLAPPED { ULONG_PTR Internal; ULONG_PTR InternalHigh; union { struct { DWORD Offset; DWORD OffsetHigh; } DUMMYSTRUCTNAME; PVOID Pointer; } DUMMYUNIONNAME; HANDLE hEvent; } OVERLAPPED, *LPOVERLAPPED; 参数: Internal: 预留给操作系统使用.它指定一个独立于

C语言----结构体---结构体与函数

结构作为参数的函数 整个结构可以作为参数传入函数 这时是在函数中新建了一个结构变量,并复制调用这个结构的值(重点,只是把值传入函数,而函数外面真正的变量并没有改变,与数组不同) 函数也可以返回一个结构 直接来个简单的例子吧: 问题:用户输入今天的日期,输出明天的日期. 提示:闰年,每个月最后一天, 代码: #include <stdio.h>#include <stdbool.h>/* 根据今天的日期算出明天的日期.*/ //结构体放在函数外侧,相当于一个全局变量,所有的函数都能使

【学习笔记】【C语言】结构体和函数

1 #include <stdio.h> 2 struct Student 3 { 4 int age; 5 int no; 6 }; 7 8 // 如果结构体作为函数参数,只是将实参结构体所有成员的值对应地赋值给了形参结构体的所有成员 9 // 修改函数内部结构体的成员不会影响外面的实参结构体 10 void test(struct Student s) 11 { 12 s.age = 30; 13 s.no = 2; 14 } 15 16 // 会影响外面的实参结构体 17 void te

jQuery源码分析:源码结构与核心函数

jQuery源码分析-03构造jQuery对象-源码结构和核心函数 jQuery.fn和jQuery.prototype区别

MySQL mysqldump 导入/导出 结构&amp;数据&amp;存储过程&amp;函数&amp;事件&amp;触发器

———————————————-库操作———————————————-1.①导出一个库结构 mysqldump -d dbname -u root -p > xxx.sql ②导出多个库结构 mysqldump -d -B dbname1 dbname2 -u root -p > xxx.sql 2.①导出一个库数据 mysqldump -t dbname -u root -p > xxx.sql ②导出多个库数据 mysqldump -t -B dbname1 dbname2 -u r

PHP5.4 循环结构、系统函数和自定义函数

1.while.for.break.continue <?php $i=1; while($i<=5){     echo "the number is".$i."<br>";     $i++; } ?> <?php $i=1; do {     echo "**********"."<br>";     $i++; }while($i<10);   ?> <

C语言中结构体在函数中的应用

一.结构体与函数参数结构体作函数参数可分为传值与传指针.1.传值时结构体参数会被拷贝一份,在函数体内修改结构体参数成员的值实际上是修改调用参数的一个临时拷贝的成员的值,这不会影响到调用参数.在这种情况下,由于涉及到结构体参数的拷贝,程序空间及时间效率都会受到影响,所以这种方法基本不用.例如:typedef struct tagSTUDENT{char name[20];int age;}STUDENT; void fun(STUDENT stu){printf("stu.name=%s,stu.

ffmpeg中对AVInputFormat结构体中函数的调用

http://blog.csdn.net/junllee/article/details/7722605 opt_input_file()->      avformat_open_input()->             init_input()->                   av_probe_input_format()->                          av_probe_input_format2()->