我们知道当程序调用I/O设备处理一些事情时,让主程序停下来干等I/O的完成是没有效率的。。对这个问题有下面几种解决方法:
方法一:使用另一个线程进行I/O。问题是在主线程中操控多个线程,如何设置同步机制、如何处理错误情况都是非常复杂麻烦的。
方法二:使用overlapped I/O(就是所谓的异步asynchronous I/O,第四章讲到了同步机制),你可以让这些I/O操作并行处理。
===================================================================
在对overlapped I/O的具体讨论之前,先介绍Win32中执行I/O的基本函数。
1、打开资源
HANDLE CreateFile(
LPCTSTR lpFileName, // 指向文件名的指针
DWORD dwDesiredAccess, // 访问模式(写 / 读)
DWORD dwShareMode, // 共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 指向安全属性的指针
DWORD dwCreationDisposition, // 如何创建
DWORD dwFlagsAndAttributes, // 文件属性
HANDLE hTemplateFile // 用于复制文件句柄
);
其中第六个参数dwFlagsAndAttributes是关键,可以由多个数值组合一起而完成,其中最重要的一个数值就是FILE_FLAG_OVERLAPPED,这个标记设置成功,对文件的每一个操作都将是异步的。
2、读操作
BOOL ReadFile( HANDLE hFile, //欲读文件 LPVOID lpBuffer, //用于保存读入数据的一个缓冲区 DWORD nNumberOfBytesToRead, //要读入的字节数 LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针 LPOVERLAPPED lpOverlapped //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数指向一个OVERLAPPED结构。 //该结构定义了一次异步读取操作。否则,应将这个参数设为NULL );
3、写操作
BOOL WriteFile( HANDLE hFile, // 欲写文件 LPCVOID lpBuffer, // 数据缓存区指针 DWORD nNumberOfBytesToWrite, // 你要写的字节数 LPDWORD lpNumberOfBytesWritten, // 用于保存实际写入字节数的存储区域的指针 LPOVERLAPPED lpOverlapped // OVERLAPPED结构体指针 );
注意:在CreateFile()的第6个参数被指定为FILE_FLAG_OVERLAPPED后,你必须在上述的lpOverlapped参数中提供一个指针,指向一个OVERLAPPED结构。
4、OVERLAPPED结构
typedef struct _OVERLAPPED { DWORD Internal; //预留给操作系统使用。它指定一个独立于系统的状态,当GetOverlappedResult函数返回时没有设置扩展错误信息ERROR_IO_PENDING时有效 DWORD InternalHigh; // 预留给操作系统使用。它指定长度的数据转移,当GetOverlappedResult函数返回TRUE时有效 DWORD Offset; //该文件的位置是从文件起始处的字节偏移量。调用进程设置这个成员之前调用ReadFile或WriteFile函数。当读取或写入命名管道和通信设备时这个成员被忽略设为零 DWORD OffsetHigh; //指定文件传送的字节偏移量的高位字。当读取或写入命名管道和通信设备时这个成员被忽略设为零。 HANDLE hEvent; //一个手动重置的event对象,当overlapped I/O完成时即被激发。 } OVERLAPPED,*LPOVERLAPPED;
注意第三个参数和第五个参数