《Win32多线程程序设计》学习笔记 第6章 Overlapped I/o 在你的身后变戏法

摘要:
操作系统使用线程来完成重叠的I/O。Win32文件操作函数Win32中有三个基本函数来执行I/O。WriteFile。关闭文件并调用CloseHandle。这些操作都使用相同的文件句柄。每个读/写操作必须包括文件位置。它必须用ReadFile和WriteFile完成。它使用自己的文件句柄作为同步机制。

这章很重要,所以才把放到最后写,压轴,同时希望自己能认真的总结一下。这一章主要就是异步编程的内容,自己的理解

Overlapped I/O是win32的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。事实上,操作系统内部正是以线程来完成overlapped I/O,你可以获得线程的所有利益不需要付出什么代价。

Win32文件操作函数

win32中有3个基本的函数来执行I/O,分别是CreateFile, ReadFile, WriteFile. 关闭文件调用CloseHandle即可。

CreateFile可以用来打开各种资源,包括(不限于)

  • 文件(硬盘,光盘,软盘或其他)
  • 串行口和并行口
  • Named Pipes
  •  Console

HANDLE CreateFile(
  LPCTSTR lpFileName, 
//文件名称
  DWORD dwDesiredAccess, //存取模式,读或写
  DWORD dwShareMode,    //共享模式
  LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全属性
  DWORD dwCreationDisposition,   //如何产生
  DWORD dwFlagsAndAttributes,     //文件属性
  HANDLE hTemplateFile          //临时文件,将拥有全部的属性拷贝
); 

第6个参数dwFlagsAndAttributes是使用overlapped I
/O的关键。可以是多个数值组合在一起。对于overlapped I/O关键的是FILE_FLAG_OVERLAPPED。通过这个参数可以指定是同步或者异步访问,不能2个都指定。

overlapped I/O可以同时读或写文件的许多部分,这些操作都使用相同的文件handle。因此,当你使用overlapped I/O时,每个读写操作都要包含文件位置。如果有多个overlapped请求,那么执行的次序无法保证。不能使用标准的C库来实现overlapped 操作,必须要以ReadFile和WriteFile来完成。

BOOL ReadFile( 
  HANDLE hFile,      
//欲读的文件
  LPVOID lpBuffer,   //接受数据的缓冲区
  DWORD nNumberOfBytesToRead,   // 欲读取的字节个数
  LPDWORD lpNumberOfBytesRead,  // 实际读取的字节个数的地址
  LPOVERLAPPED lpOverlapped    // 指针,指向overlapped info结构
); 

BOOL WriteFile( 
  HANDLE hFile, 
  LPCVOID lpBuffer, 
  DWORD nNumberOfBytesToWrite, 
  LPDWORD lpNumberOfBytesWritten, 
  LPOVERLAPPED lpOverlapped
); 

typedef 
struct _OVERLAPPED {  
    ULONG_PTR Internal;  
//通常保留,当GetOverLappedResult返回False时,有用
    ULONG_PTR InternalHigh;  /通常保留,当GetOverlappedResult返回TRue时,有用
    union {    
      
struct {      
        DWORD Offset;      
//读写的偏移地址
        DWORD OffsetHigh;    //64位地址中较高的32位
      };    
      PVOID Pointer;  
    };  
    HANDLE hEvent;  
//一个手动重置的eventuixiang,当overlapped 完成时激发
} OVERLAPPED,  *OVERLAPPEDLPOVERLAPPED;

OVERLAPPED的2个功能,识别每一个正在进行的overlapped操作,你和系统之间的共享区域,参数在这个区域中双向传递。
由于OVERLAPPED结构的生命周期超越ReadFile和writeFile,所以要将其放在一个安全的地方,就是heap。

 被激发的File Handles

 最简单的overlapped I/O类型,是使用它自己的文件handle作为同步机制。首先以FILE_FLAG_OVERLAPPED告诉win32说你不要使用默认的同步IO。然后设立一个OVERLAPPED结构,其中包含“IO请求”的所有必要参数,并以此识别这个IO请求,直到完成为止。接下来,调用ReadFile并以OVERLAPPED结构的地址作为最后一个参数。这时,就可以等待win32为你处理io,你可以做其他的事情了。 如果你需要等待overlapped IO的执行结果,作为WaitForMultipleObjects的一部分,请在handle数组中加上这个文件handle。 当完成操作后,可调用GetOverlappdedResult以确定结果如何。

《Win32多线程程序设计》学习笔记 第6章 Overlapped I/o 在你的身后变戏法第1张《Win32多线程程序设计》学习笔记 第6章 Overlapped I/o 在你的身后变戏法第2张代码
BOOL WINAPI GetOverlappedResult(
   HANDLE hFile,       
//文件或者设备的handle
   LPOVERLAPPED lpOverlapped,  //一个指向OVERLAPPED结构的指针
   LPDWORD lpNumberOfBytesTransferred,   //指针,获得真正传送的字节个数
   BOOL bWait      //是否要等待操作完成
);

返回值:如果overlapped操作成功,返回TRUE,失败返回FALSE。如果bWait为False而overlapped还没有完成,GetLastError会传回ERROR_IO_INCOMPLETE.

我们要注意,虽然我们要求进行overlapped操作,但如果数据可以很快的传送,那么文件操作就可能会在REadfile返回之前完成,而ReadFile返回TRUE。

如果请求进行overlapped操作,那么ReadFile和WriteFile常规情况下会返回FALSE, 我们必须调用GetLastError并确定它传回ERROR_IO_PENDING,以为着IO操作被放进队列中等待执行。如果是其他返回值,就代表一个真正的错误了。

被激发的Event对象

 以文件handle作为激发机制,如果在一个文件上有多个overlapped操作时,无法得知那个overlapped操作完成了。这时,我们可以使用OVERLAPPED结构中的最后一个event handle位,当这个栏位设为一个event对象时,系统核心会在overlapped操作完成时,自动将这个event 对象激发。每个操作都有独一无二的event对象,所使用的event对象必须是手动重置的。

免责声明:文章转载自《《Win32多线程程序设计》学习笔记 第6章 Overlapped I/o 在你的身后变戏法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇WPF 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改PG 通过 auto_explain 模块查看函数中的 SQL 的执行计划,从而进行性能优化(瓶颈定位)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

.NET上传大文件的三种解决方案

ASP.NET上传文件用FileUpLoad就可以,但是对文件夹的操作却不能用FileUpLoad来实现。 下面这个示例便是使用ASP.NET来实现上传文件夹并对文件夹进行压缩以及解压。 ASP.NET页面设计:TextBox和Button按钮。 TextBox中需要自己受到输入文件夹的路径(包含文件夹),通过Button实现选择文件夹的问题还没有解决,...

svnlook

SYNOPSIS 总览 svnlookcommand/path/to/repos [options] [args] OVERVIEW 概述 Subversion 是一个版本控制系统,允许保存旧版本的文件和目录 (通常是源代码),保存一个记录何人,何时,为何作出修改等等信息的日志,与 CVS,RCS 或者 SCCS 工具类似。 Subversion...

python网络编程——IO多路复用之select

1 IO多路复用的概念         原生socket客户端在与服务端建立连接时,即服务端调用accept方法时是阻塞的,同时服务端和客户端在收发数据(调用recv、send、sendall)时也是阻塞的。原生socket服务端在同一时刻只能处理一个客户端请求,即服务端不能同时与多个客户端进行通信,实现并发,导致服务端资源闲置(此时服务端只占据 I/O,...

C#调用java类、jar包方法。

一、将已经编译后的java中Class文件进行打包;打包命令JAR 如:将某目录下的所有class文件夹全部进行打包处理; 使用的命令:jar cvf test.jar -C com/ . 其中test.jar为要生成的jar包;com/ . 为指定的当前目录下的文件夹,该文件夹包括子文件夹及class文件; 二、到IKVM官方网站下载IKVM需要的组件 ...

Excel 数据对比,窗口并列排序操作(xlw文件格式的由来)

步骤1:打开Excel文件,输入一些数据 步骤2:点击视图,创建新窗口(这里就会创建一个和步骤1一抹一样的的表格,我们可以在任务栏上看到) 第三步:点击视图里面的全部重排按钮,在重拍窗口里面选择需要拍了的方式(自己选择,这里我选择垂直并排) 到这来,两个一模一样的垂直的窗口就显示出来了,如下所示 补充说明:如果我们想下次打开这个文件还是这种垂直并排...

Effective Refactoring in C++ (三)

高效重构 当我们熟练掌握了重构技术后,还不能就此说自己在实践中已经可以安全而高效地实施重构了! 因为落到真正的工程实践环境,安全和高效的重构过程还需要好用的IDE工具,成熟的自动化测试套件,快速高效的开发构建环境,以及良好的编码习惯来支撑. 本节针对C++语言,总结了一些对实施重构非常有用的工程实践经验. 当然其中决大部分也适用于C语言开发. 语言相关 由...