最简单的 overlapped I/O 类型,是使用它自己的文件 handle 作为同步机制。首先你以 FILE_FLAG_OVERLAPPED 告诉 Win32 说你不要使用默认的同步 I/O。然后,你设立一个 OVERLAPPED 结构,其中内含“I/O 请求”的所有必要参数,并以此识别这个“I/O 请求”,直到它完成为止。接下来,调用 ReadFile() 并以 OVERLAPPED 结构的地址作为最后一个参数。这时候,理论上,Win32 会在后台处理你的请求。你的程序可以放心地继续处理其他事情。

    如果你需要等待 overlapped I/O 的执行结果, 作为WaitForMultipleObjects() 的一部分, 请在 handle 数组中加上这个文件handle。文件 handle 是一个核心对象,一旦操作完毕即被激发。当你完成操作之后,请调用 GetOverlappedResult() 以确定结果如何。
    
    调用 GetOverlappedResult() , 你获得的结果和“ 调用 ReadFile() 或WriteFile() 而没有指定 overlapped I/O”所传回的东西一样。这个函数的价值在于,在文件操作真正完成之前,你不可能确实知道它是否成功。甚至在一个完美无瑕的环境下读一个已知的磁盘文件,也有可能发生硬件错误、服务器当掉,或任何未能预期的错误。因此,调用 GetOverlappedResult() 是很重要的。
    
        GetOverlappedResult() 规格如下:
    
    BOOL GetOverlappedResult(
        HANDLE hFile,
        LPOVERLAPPED lpOverlapped,
        LPDWORD lpNumberOfBytesTransferred,
        BOOL bWait
    );
    参数
    hFile                 文件或设备(device)的 handle。
    lpOverlapped             一个指针,指向 OVERLAPPED 结构。
    lpNumberOfBytesTransferred     一个指针,指向 DWORD,用以表示真正被传输的字节个数。
    bWait                 一个布尔值,用以表示是否要等待操作完成。TRUE 表示要等待。
    
    返回值
        如果 overlapped 操作成功,此函数传回 TRUE。失败则传回 FALSE。GetLastError() 可获得更详细的失败信息。如果 bWait 为 FALSE 而overlapped 还是没有完成,GetLastError() 会传回ERROR_IO_INCOMPLETE。
    
        列表6-1 所显示的程序代码从文件 C:\WINDOWS\WINFILE.EXE 的第1500 位置处读入 300 个字节。这段代码放在书附盘片的 IOBYFILE 程序中。
            列表6-1 引用自 IOBYFILE.C—overlapped I/O
                with a signaled file handle
#0001 int ReadSomething()
#0002 {
#0003         BOOL rc;
#0004         HANDLE hFile;
#0005         DWORD numread;
#0006         OVERLAPPED overlap;
#0007         char buf[512];
#0008
#0009         // open the file for overlapped reads
#0010         hFile = CreateFile( "C:\\WINDOWS\\WINFILE.EXE",
#0011                 GENERIC_READ,
#0012                 FILE_SHARE_READ|FILE_SHARE_WRITE,
#0013                 NULL,
#0014                 OPEN_EXISTING,
#0015                 FILE_FLAG_OVERLAPPED,
#0016                 NULL
#0017             );
#0018         if (hFile == INVALID_HANDLE_VALUE)
#0019         return -1;

#0020
#0021         // Initialize the OVERLAPPED structure
#0022         memset(&overlap, 0, sizeof(overlap));
#0023         overlap.Offset = 1500;
#0024
#0025         // Request the data
#0026         rc = ReadFile(
#0027                 hFile,
#0028                 buf,
#0029                 300,
#0030                 &numread,
#0031                 &overlap
#0032             );
#0033
#0034         if (rc)
#0035         {
#0036             // The data was read successfully
#0037         }
#0038         else
#0039         {
#0040             // Was the operation queued ?
#0041             if (GetLastError() == ERROR_IO_PENDING)
#0042             {
#0043                 // We could do something else for awhile here...
#0044
#0045                 WaitForSingleObject(hFile, INFINITE);
#0046                 rc = GetOverlappedResult(
#0047                             hFile,
#0048                             &overlap,
#0049                             &numread,
#0050                             FALSE
#0051                     );
#0052             }
#0053             else
#0054             {
#0055                 // Something went wrong
#0056             }
#0057         }
#0058
#0059         CloseHandle(hFile);
#0060

#0061         return TRUE;
#0062         }

    在这段程序代码中我们得特别注意几点。第一,虽然你要求一个overlapped 操作,但它并不一定就是 overlapped!如果数据已经被放进 cache中,或如果操作系统认为它可以很快速地取得那份数据,那么文件操作就会在ReadFile() 返回之前完成,而 ReadFile() 将传回 TRUE。这种情况下,文件handle 处于激发状态,而对文件的操作可被视为就像 overlapped 一样。
    
    下一个需要注意的是,如果你要求一个文件操作为 overlapped,而操作系统把这个“操作请求”放到队列中等待执行,那么 ReadFile() 和 WriteFile()都会传回 FALSE 以示失败。这个行为并不是很直观, 你必须调用GetLastError() 并确定它传回 ERROR_IO_PENDING,那意味着“overlappedI/O 请求”被放进队列之中等待执行。GetLastError() 也可能传回其他的值,例如 ERROR_HANDLE_EOF,那就真正代表一个错误了。

    请注意 overlapped I/O 如何解决“没有文件指针”这个问题。事实上OVERLAPPED 结构本身就包含了“这个操作应该从哪里开始”的信息。那当然是值得注意的东西,但是在列表6-1 中未显示出来。OVERLAPPED 结构有能力处理 64 位的偏移值,因此即使面对非常巨大的文件也不怕。
    
    为了等待文件操作完成, 我把文件的 handle 交给WaitForSingleObject()。一旦 overlapped 操作完成,该文件 handle 就会成为激发状态。我所举的这个例子过于简单,真实世界里,可能会在程序的某个集中处,等待许多个 handles。

    列表6-1 调用 WaitForSingleObject() 其实是多余的, 因为GetOverlappedResult() 就可以用来等待 overlapped 操作的完成。不过由于实际上你常常会以一个 Wait...() 函数去等待 overlapped 操作完成,所以我才做这样的示范。

第6章 Overlapped I/O, 在你身后变戏法 ---被激发的 File Handles -3的更多相关文章

  1. 第6章 Overlapped I/O, 在你身后变戏法 ---被激发的 Event 对象 -4

    以文件 handle 作为激发机制,有一个明显的限制,那就是没办法说出到底是哪一个 overlapped 操作完成了.如果每个文件 handle 只有一个操作等待决定,上述问题其实并不成为问题.但是如 ...

  2. 第6章 Overlapped I/O, 在你身后变戏法 ---1

    这一章描述如何使用 overlapped I/O(也就是 asynchronous I/O).某些时候 overlapped I/O 可以取代多线程的功用.然而,overlapped I/O 加上co ...

  3. 第6章 Overlapped I/O, 在你身后变戏法 ---Win32 文件操作函数 -2

    Win32 之中有三个基本的函数用来执行 I/O,它们是:        i CreateFile()        i ReadFile()        i WriteFile()    没有另外 ...

  4. [转]重叠IO

    本章回答了如下几个问题: ◆ 什么是Overlapped I/O?为什么需要Overlapped I/O?如何让数据传输支持Overlapped I/O? ◆ 数据传输结束后,Win32提供了哪些方式 ...

  5. 异步设备IO:OVERLAPPED和IOCompletionPort

    异步设备IO:OVERLAPPED和IOCompletionPort 本文内容为<windows核心编程>第10章内容的总结,仅记录一些本人感兴趣的内容. 1:OVERLAPPED &qu ...

  6. RHCE学习笔记 管理1 (第三~五章)

    第三章 红帽企业linux 获取帮助 (略) man .pinfo. 第四章 编辑文件 1.输出重定向到文件和程序 >file    定向文件(覆盖) >>file   定向文件(附 ...

  7. Synchronization and Overlapped Input and Output

    You can perform either synchronous or asynchronous (also called overlapped) I/O operations on files, ...

  8. C10K问题渣翻译

    The C10K problem [Help save the best Linux news source on the web -- subscribe to Linux Weekly News! ...

  9. 微软ASP.NET网站部署指南(10):迁移至SQL Server

    1.  综述 第2章的部署SQL Server Compact和第9章的部署数据库更新里解释了为什么终于要升级到完整版SQL Server .本章节将告诉你怎样来做. SQL Server Expre ...

随机推荐

  1. Java的常用操作符

    操作符用于接受一个或多个参数,并生成一个新的值.加号和一元的正号(+).减号和一元的负号(一).乘号(*).除号(/)以及赋值号(=)的用法和大多数编程语言都类似. 操作符作用于操作数,生成一个新值. ...

  2. 写给后端的前端笔记:浮动(float)布局

    写给后端的前端笔记:浮动(float)布局 这篇文章主要面向后端人员,对前端有深刻了解的各位不喜勿喷. 起因 前一阵子我一个后端的伙伴问我,"前端的左飘怎么做?",我立马就懵了,& ...

  3. JRE 和 JDK 的区别

    JRE顾名思义是java运行时环境,包含了java虚拟机,java基础类库.是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的.   JDK顾名思义是java开发 ...

  4. 将git commit的默认编辑器从nano转为vim

    修改系统的配置 git config --global core.editor vim 针对 git 项目修改 .git/config core 中添加 editor=vim

  5. 【Java数据结构学习笔记之二】Java数据结构与算法之队列(Queue)实现

      本篇是数据结构与算法的第三篇,本篇我们将来了解一下知识点: 队列的抽象数据类型 顺序队列的设计与实现 链式队列的设计与实现 队列应用的简单举例 优先队列的设置与实现双链表实现 队列的抽象数据类型 ...

  6. hdu 2066 最短路水题

    题意:给出多个可选择的起始点和终点,求最短路 思路:执行起始点次的spfa即可 代码: #include<iostream> #include<cstdio> #include ...

  7. wait与sellp方法区别

    Java Thread(线程)案例详解sleep和wait的区别    上次对Java Thread有了总体的概述与总结,当然大多都是理论上的,这次我将详解Thread中两个常用且容易疑惑的方法.并通 ...

  8. YYHS-怎样更有力气

    题目描述 OI大师抖儿在夺得银牌之后,顺利保送pku.这一天,抖儿问长者:"我虽然已经保送了,但我的志向是为国家健康工作五十年.请问我应该怎样变得更有力气?"  长者回答:&quo ...

  9. 【集美大学1411_助教博客】团队作业1——团队展示&选题 成绩

    第一次团队作业已经新鲜出炉啦,各位同学请查收.截止日期前,全班都按时提交了作业,而且有的团队还提交了两次呢,下次不要这样啦~ 题目 团队作业1--团队展示&选题 回顾 个人作业1--四则运算题 ...

  10. 事后诸葛亮分析(Beta阶段)

    设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 解决用户想要随时锻炼四则运算能力的问题:定义的很清楚:有清晰描述. 2.是否有充足的时间来做计划? ...