OVERLAPPED結構與GetOverlappedResult函數

來源:互聯網
上載者:User

標籤:format   api   null   --   驅動程式   傳輸   status   成功   gre   

非同步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.     //  
  5.     // Did caller specify an event to the original operation or was the  
  6.     // default (file handle) used?  
  7.     //  
  8.   
  9.     if (lpOverlapped->Internal == (DWORD)STATUS_PENDING ) {  
  10.         if ( bWait ) {  
  11.             //  
  12.             //現在還是PENDING,且還需要等待,則無限期等待。  
  13.             //很多人會自己調用WaitForSingleObject後再調用GetOverlappedResult,其實看起來  
  14.             //沒多少必要。  
  15.             //  
  16.             WaitReturn = WaitForSingleObject(  
  17.                             ( lpOverlapped->hEvent != NULL ) ?  
  18.                                 lpOverlapped->hEvent : hFile,  
  19.                             INFINITE  
  20.                             );  
  21.             }  
  22.         else {  
  23.             WaitReturn = WAIT_TIMEOUT;  
  24.             }  
  25.   
  26.         if ( WaitReturn == WAIT_TIMEOUT ) {  
  27.             //  !bWait and event in not signalled state  
  28.             SetLastError( ERROR_IO_INCOMPLETE );  
  29.             return FALSE;  
  30.             }  
  31.   
  32.         if ( WaitReturn != 0 ) {  
  33.              return FALSE;    // WaitForSingleObject calls BaseSetLastError  
  34.              }  
  35.         }  
  36.   
  37.     *lpNumberOfBytesTransferred = (DWORD)lpOverlapped->InternalHigh;  
  38.   
  39.     if ( NT_SUCCESS((NTSTATUS)lpOverlapped->Internal) ){  
  40.         return TRUE;  
  41.         }  
  42.     else {  
  43.         BaseSetLastNTError( (NTSTATUS)lpOverlapped->Internal );  
  44.         return FALSE;  
  45.         }  
  46. }  


補充:(2009-10-8)

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

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

Internal成員:這個成員用來儲存已處理的I/O請求的錯誤碼.

InternalHigh成員:當非同步I/O請求完成的時候,這個成員用來儲存已傳輸的位元組數。

在當初設計OVERLAPPED結構的時候,Microsoft決定不公開Internal和InternalHigh成員(名副其實)。隨著時間的推移,Microsoft認識到這些成員包含的資訊會對開發人員有用,因此把它們公開了。但是,Microsoft沒有改變這些成員的名字,這是因為作業系統的原始碼頻繁地用到它們,而Microsoft並不想為此修改原始碼。

-------

由於Microsoft公開了這些成員,所以我們看到並不一定需要GetOverLappedResult了。:)

OVERLAPPED結構與GetOverlappedResult函數

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.