博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Overlapped I/O
阅读量:5946 次
发布时间:2019-06-19

本文共 3504 字,大约阅读时间需要 11 分钟。

Overlapped I/O是Windows系统上的Asynchronous I/O implementation。啥叫asynchronous I/O ?借用Linux Man page中对AIO的介绍:

The POSIX asynchronous I/O (AIO) interface allows applications to initiate one or more I/O operations that are performed asynchronously (i.e., in the background). The application can elect to be notified of completion of the I/O operation in a variety of ways: by delivery of a signal, by instantiation of a thread, or no notification at all.

AIO让应用发起一个操作请求,让这个请求被异步地执行。应用可以选择在操作完成时被通知到或者不被通知。 

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

 

关于这个数据结构的详细介绍可以参考:。 概括来说,Internal,InternalHigh都是内部使用的,不建议直接使用;Offset + OffsetHigh用于有offset概念的handle;Pointer是保留给系统使用的;hEvent指向一个event,当操作完成后,这个event会被系统设置成signalled状态。

看起来,这个数据结构本身并没有提供很多信息,那如何使用这个数据结构呢?

  

OVERLAPPED使用之一:内核对象(handle)

无论是对一个Socket或者文件或者其他什么对象操作,总有一个handle来指向这个对象。当对这个对象发出操作请求后,过一段时间就可以使用该handle和Overlapped对象进行查询,之前的那个请求是否完成。下面是一个例子:

用overlapped模型读一个磁盘文件内容。

   1.把设备句柄看作同步对象,ReadFile将设备句柄设为无信号。ReadFile 异步I/O字节位置必须在OVERLAPPED结构中指定。

   2.完成I/O,设置信息状态。为有信号。

   3.WaitForSingleObject或WaitForMultipleObject判断或者异步设备调用GetOverLappedResult函数。

 

#include <Windows.h>
#define READ_SIZE 1024
int main()
{
    BOOL rc;
    HANDLE hFile;
    DWORD numread;
    OVERLAPPED overlap;
    
char buf[READ_SIZE];
    
char szPath[MAX_PATH];
    GetWindowsDirectory(szPath, 
sizeof(szPath));
    strcat(szPath, 
"
\\WINHLP32.EXE
");
    hFile = CreateFile( szPath,
                    GENERIC_READ,
                    FILE_SHARE_READ|FILE_SHARE_WRITE,
                    NULL,
                    OPEN_EXISTING,
                    FILE_FLAG_OVERLAPPED,
                    NULL
                );
    
if (hFile == INVALID_HANDLE_VALUE)
    {
        printf(
"
Could not open %s\n
", szPath);
        
return -
1;
    }
    memset(&overlap, 
0
sizeof(overlap));
    overlap.Offset = 
1500;
    rc = ReadFile(
                hFile,
                buf,
                READ_SIZE,
                &numread,
                &overlap
            );
    printf(
"
Issued read request\n
");
    
if (rc)
    {
        printf(
"
Request was returned immediately\n
");
    }
    
else
    {
        
if (GetLastError() == ERROR_IO_PENDING)
        {
            printf(
"
Request queued, waiting...\n
");
            WaitForSingleObject(hFile, INFINITE);
            printf(
"
Request completed.\n
");
            rc = GetOverlappedResult(
                                    hFile,
                                    &overlap,
                                    &numread,
                                    FALSE
                                );
            printf(
"
Result was %d\n
", rc);
        }
        
else
        {
            printf(
"
Error reading file\n
");
        }
    }
    CloseHandle(hFile);
    
return EXIT_SUCCESS;
}

 

OVERLAPPED使用之二: 事件通知

每一个异步操作,都有一个OVERLAPPED的instance与之相关联,因此,当之前提交的异步操作完成后,可以使用OVERLAPPED中的hEvent来获取通知。写完示例程序可以贴出来。

 

Limitation:

1. WaitForMultipleObjects最多可以等待MAXIMUM_WAIT_OBJECTS(64)个对象,当提交的请求比较多(>64)时,就没法同时等。

2. 只能使用一个file handle;

 

OVERLAPPED使用之三: COMPLETION ROUTINE

另外一种方法是注册一个回调函数,在一个Overlapped I/O完成之后,系统调用该回调函数。OS在有信号状态下(设备句柄),才会调用回调函数(可能有很多APCS等待处理了),传给它完成I/O请求的错误码,传输字节数和Overlapped结构的地址。看看OVERLAPPED的定义,这个回调函数是没法跟OVERLAPPED进行关联了,那在哪里关联呢?答案是在每次请求时关联,比如WSARecv, ReadFileEx, WSASend 等函数都有一个参数为LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,这就是call back函数可以注册的地方。写完示例程序可以贴出来。

可以注意到,在这种方式时,并不需要每个IO request创建一个OVERLAPPED实例,因为没有用到OVERLAPPED里的任何信息。大家共享一个就可以了。

 

Limitation:

1. 只有发出overlapped IO请求的线程才可以提供callback函数,每个callback都会创建一个新线程,那么就是每个request都要创建线程,用完销毁,开销太大。

2. 只能使用一个file handle;

 

OVERLAPPED使用之四: IOCP

IOCP是在OVERLAPPED IO基础上的扩展。功能更加强大。OVERLAPPED IO会创建IO request 队列,当有异步请求时,就把请求放到这个队列里,系统会从队列中取请求并处理;IOCP主要是接近请求完成后通知的问题,IOCP是又创建了一个完成队列,当OVERLAPPED IO中的request 队列中有request被完成时,就放到IOCP的完成队列中,App的GetQueuedCompletionStatus从完成队列中取一个completion packet,进行处理。

所以,IOCP是以OVERLAPPED IO为基础的完成通知机制,对OVERLAPPED数据结构中的信息被不真正关心。但是必须要有一个OVERLAPPED的instance。

 

转载于:https://www.cnblogs.com/whyandinside/archive/2011/11/13/2247138.html

你可能感兴趣的文章
Java递归列出所有文件和文件夹
查看>>
[关于SQL]查询成绩都大于80分的学生
查看>>
Delphi(Tuxedo,BDE,ADO)三合一数据集组件HsTxQuery
查看>>
LeetCode - Longest Common Prefix
查看>>
Android图片处理
查看>>
2015年第21本:万万没想到,用理工科思维理解世界
查看>>
大家谈谈公司里的项目经理角色及职责都是干什么的?
查看>>
剑指offer
查看>>
Velocity魔法堂系列二:VTL语法详解
查看>>
NopCommerce架构分析之八------多语言
查看>>
转:Eclipse自动补全功能轻松设置
查看>>
mysql update操作
查看>>
Robots.txt - 禁止爬虫(转)
查看>>
MySQL数据库
查看>>
Mysql 监视工具
查看>>
SSH详解
查看>>
ASM概述
查看>>
【290】Python 函数
查看>>
godaddy域名转发(域名跳转)设置教程
查看>>
silverlight学习布局之:布局stackpanel
查看>>