随笔 - 60, 文章 - 0, 评论 - 197, 引用 - 0
数据加载中……

简析 Win32 异步 IO 机制 (一)


简而言之,Overlapped IO 即异步 IO, 用于并发读写数据

一、Win32 的文件操作函数

   HANDLE CreateFile(
          LPCTSTR lpFileName,  // 指向文件名称
          DWORD dwDesiredAccess,  // 存取模式(读或写)
          DWORD dwShareMode,  // 共享模式
          LPSECURITY_ATTRIBUTES lpSecurity_attributes, // 安全属性
          DWORD dwCreattionDisposition,  // 如何产生
          DWORD dwFlagsAndAttributes,  // 文件属性
          HANDLE hTemplateFile  // 一个文件属性,将拥有全部文件属性拷贝
        )

   CreateFile 可以打开各种资源,而非仅仅文件, 包括:
   * 文件
   * 串行口,并行口
   * Named Pipe
   * Console

   其参数 dwFlagsAndAttributes 是使用 Overlapped IO 的关键

   Overlapped IO 的基本形式是以 ReadFile() 和 WriteFile() 来完成的, 二者原型如下:

   BOOL ReadFile(
        HANDLE hFile, // 欲读取的文件
        LPVOID lpBuffer,  // 接收缓冲
        DWORD nNumberOfBytesToRead,  // 读取字节数
        LPDWORD lpNumberOfBytesToRead,  // 实际读取的字节数
        LPOVERLAPPED lpOverlapped  // 指向一个 overlapped info
   );

   BOOL WriteFile(
        HANDLE hFile,  // 要写的文件
        LPVOID lpBuffer,  // 数据缓冲区
        DWORD nNumberOfBytesToWrite,  // 打算写入的字节数
        LPVOID lpNumberOfBytesWritten, // 实际写入的字节数
        LPOVERLAPPED lpOverlapped // 指向一个 overlapped info
   );

  
   如果 CreateFile 的第 6 个参数 dwFlagsAndAttributes 被指定为 FILE_FLAG_OVERLAPPED, 则 ReadFile() 和 WriteFile()
   的参数需提供一个指向 OVERLAPPED 的结构指针


二、OVERLAPPED 结构
  
   typedef struct _OVERLAPPED {
       DWORD Internal;
       DWORD InternalHigh;
       DWORD Offset;  // 文件被读或被写的偏移
       DWORD OffsetHigh;
       HANDLE hEvent;
   } OVERLAPPED


三、Overlapped 如何运作

   以最简单的 Overlapped IO 为例

   (1) 你在 CreateFile() 时指定 FILE_FLAG_OVERLAPPED 告诉 Win32 你要使用 Overlapped IO 特性
   (2) 调用 ReadFile(), 并传递一个指向 Overlapped 的指针
   (3) Win32 会在后台处理你的请求,你的程序可以继续做其它事情
   (4) 如果你要等待 Overlapped IO 的结果,请用 WaitForMultipleObject() 等待你读写文件的 handle, 因为文件 handle 是一个核心对象, 一旦操作完成就被激发。当你完成其它操作之后,可调用 GetOverlappedResult() 确定结果如何。

 1 
 2 HANDLE hFile;
 3 OVERLAPPED overlap;
 4 
 5 // Open the file for overlapped reads
 6 hFile = CreateFile( szPath,
 7                     GENERIC_READ,
 8                     FILE_SHARE_READ|FILE_SHARE_WRITE,
 9                     NULL,
10                     OPEN_EXISTING,
11                     FILE_FLAG_OVERLAPPED,
12                     NULL
13     );
14 
15 if (hFile == INVALID_HANDLE_VALUE)
16     return -1;
17 
18 // Initialize the OVERLAPPED structure
19 memset(&overlap, 0sizeof(overlap));
20 overlap.Offset = 1500;
21 
22 // Request the data
23 rc = ReadFile(
24     hFile,
25     buf,
26     READ_SIZE,
27     &numread,
28     &overlap
29     );
30 
31 // Was the operation queued?
32 if (rc)
33 {
34     // The data was read successfully
35 }
36 else
37 {
38     if (GetLastError() == ERROR_IO_PENDING)
39     {
40         // We could do something else for awhile here
41         WaitForSingleObject(hFile, INFINITE);
42 
43         rc = GetOverlappedResult(
44             hFile,
45             &overlap,
46             &numread,
47             FALSE
48             );
49     }
50     else
51     {
52         // Something went wrong
53         printf("Error reading file\n");
54     }
55 }
56 
57 CloseHandle(hFile);

posted on 2009-12-01 22:23 Normandy 阅读(3103) 评论(0)  编辑 收藏 引用 所属分类: Programming


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理