OVERLAPPED结构与GetOverlappedResult函数

OVERLAPPED结构与GetOverlappedResult函数

2009-10-8编辑



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

--*/
{
    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并不想为此修改源代码。

-------

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

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
更新了下。。。 ************************************************************************ 函数名称:SP_InitComm 函数功能:初始化异步窗口操作模块 参数.一:lpComName In/Out:In 可空:N 意思:速率 返回值类型:要读取的串口号码 意思:是否初始化成功 备注: *************************************************************************/ extern "C" __declspec(dllexport) BOOL SP_InitComm(LPCTSTR lpComName); //初始化串口操作 /************************************************************************ 函数名称:SP_CloseComm 函数功能:关闭串口 返回值类型:无 意思: 备注:不在使用串口的时候可以关闭它。不然会造成下次使用出现问题 *************************************************************************/ extern "C" __declspec(dllexport) void SP_CloseComm(); /************************************************************************ 函数名称:SP_ReadComm 函数功能:读取串口数据 参数.一:tszDest In/Out:In/Out 可空:N 意思:要保存到的缓冲区,提供一个缓冲区 参数.二:dwWriteLen In/Out:In/Out 可空:N 意思:读取的预计大小,实际写出大小 返回值类型:逻辑型 意思:是否成功读取 备注: *************************************************************************/ extern "C" __declspec(dllexport) BOOL SP_ReadComm(TCHAR *pTszBuff,DWORD *pdwLen); /************************************************************************ 函数名称:SP_WriteComm 函数功能:异步发送串口数据 参数.一:tszData In/Out:In 可空:N 意思:要发送的数据字符串指针 参数.二:dwWriteLen In/Out:Out 可空:N 意思:实际发送的长度,可空 返回值类型:逻辑型 意思:是否发送成功 备注:如果错误你需要获取错误码来知道为什么错误 *************************************************************************/ extern "C" __declspec(dllexport) BOOL SP_WriteComm(TCHAR *pTszBuff,DWORD *pdwLen); /************************************************************************ 函数名称:SP_GetComCount 函数功能:获取当前系统有多少COM端口 参数.一:ComName In/Out:Out 可空:N 意思:Com字符串名称 返回值类型:int 意思:当前COM端口个数 备注:ComName会返回搜索到的最后一个COM端口名称,然后你可以根据序号来操作 *************************************************************************/ extern "C" __declspec(dllexport) DWORD SP_GetComCount(TCHAR *tszComNumber); //获取错误码 extern "C" __declspec(dllexport) DWORD SP_COM_GetLastError();
`OVERLAPPED` 结构体是用于实现异步 I/O 操作的关键结构体之一。在使用 `ReadFile` 函数进行异步读取操作时,需要先创建一个 `OVERLAPPED` 结构体,并设置好相关参数。下面是一个示例代码: ```c++ char buffer[1024]; OVERLAPPED overlapped = {0}; // 初始化为0,清空结构体 // 设置偏移量和事件对象 overlapped.Offset = 0; overlapped.OffsetHigh = 0; overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // 异步读取数据 if (ReadFile(hFile, buffer, 1024, NULL, &overlapped)) { // 同步操作,数据已经读取完成 // ... } else { // 异步操作,等待操作完成 DWORD error = GetLastError(); if (error != ERROR_IO_PENDING) { // 错误处理 // ... } else { // 等待异步操作完成 if (WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_OBJECT_0) { // 异步操作已完成 DWORD bytesRead = 0; GetOverlappedResult(hFile, &overlapped, &bytesRead, TRUE); // 处理读取到的数据 // ... } else { // 等待事件失败 // ... } } } // 关闭事件对象 CloseHandle(overlapped.hEvent); ``` 在上面的示例代码中,我们首先创建了一个 `OVERLAPPED` 结构体,并设置了偏移量和事件对象。然后,我们使用 `ReadFile` 函数进行异步读取操作。如果 `ReadFile` 函数返回 `TRUE`,则表示数据已经读取完成,可以通过 `GetOverlappedResult` 函数获取已经读取的字节数。 如果 `ReadFile` 函数返回 `FALSE`,则表示需要等待异步操作完成。我们可以通过 `GetLastError` 函数获取错误码,如果错误码为 `ERROR_IO_PENDING`,则表示异步操作已经提交,需要等待操作完成。我们可以使用 `WaitForSingleObject` 函数等待事件对象,当事件对象变为有信号状态时,表示异步操作已经完成。此时可以通过 `GetOverlappedResult` 函数获取已经读取的字节数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值