1. 异步IO起源——OVERLAPPED
typedef struct _OVERLAPPED {
ULONG_PTR Internal; //操作系统保留,指出一个和系统相关的状态
ULONG_PTR InternalHigh; //指出发送或接收的数据长度
union {
struct {
DWORD Offset; //文件传送的字节偏移量的低位字
DWORD OffsetHigh; //文件传送的字节偏移量的高位字
} DUMMYSTRUCTNAME;
PVOID Pointer; //指针,指向文件传送位置
} DUMMYUNIONNAME;
HANDLE hEvent; //指定一个I/O操作完成后触发的事件
} OVERLAPPED, *LPOVERLAPPED;
整个结构体相当于将以下参数传入
InternalHigh_out write_or_read(Pointer_OffsetHight_in, hEvent_in ) exception Internal;
2. 异步IO常用API
CreateFile
GetFileSizeEx:获取文件长度
ReadFile:读取文件
WriteFile:写入文件
3. 异步模型
1)使用设备内核对象:使用WaitForSingleObject等待异步执行完成。
2)使用事件内核对象:通过CreateEvent创建一个事件内核对象,将其传递到hEvent,然后在其它线程中WaitForSingleObject
3)可提醒IO:使用ReadFileEx,并传入一个回调函数。当调用SleepEx和其它WaitFor...函数,线程可以进入可提醒状态,就会自动执行回调函数。
4)I/O完成端口:Window提供的异步工具函数
//创建完成端口
HANDLE hIocp = CreateIoCompletationPort(INVALID_HANDLE_VALUE,nullptr,0,0);
//将hFile和IOCP绑定
CreateIoCompletationPort(hFile, hIocp,USER_KEY, 0);
//向完成端口发生一个完成消息
PostQueuedCompletationStatus(hIocp, 0, USER_KEY, &overload);
//获取完成消息
GetQueuedCompletationStatus(hIocp, &dwByteTrans(传输字节数),&ulKey(USER_KEY),&lpOverlapped);
完成端口仅仅是一个专门处理IO事件队列,这个事件队列尽可能使用了和CPU的资源创建了线程,用于等待IO事件的完成。
CreateIoCompletationPort就是创建了一个事件队列,之后将hFile和一个UserKey绑定起来,使用Overload结构体传递执和IO相关的所有参数和执行结果。
一个完成端口(事件队列)中可以塞入多个设备(HFILE),每个设备对应一个Overload,用来异步回调传递参数。
可以直接向完成端口(事件队列)发送一个空的完成消息(一般用于多次读写),也可以只依靠异步IO读写机制,让Windows API内部发送读写消息(一般只用于一次性读写)。