进行异步I/O的四种方式
1. 使用设备内核对象使用设备内核对象
2. 使用事件内核对象
3. 可提醒I/O可提醒I/O
4. I/O完成端口I/O完成端口
在进行异步I/O操作的时候
HANDLE WINAPI CreateFile(
_In_ LPCTSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
);
//dwFlagsAndAttributes这个参数必须设为FILE_FLAG_OVERLAPPED
此时需要用到OVERLAPPED的结构体
typedef struct _OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
};
PVOID Pointer;
};
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
使用事件内核对象进行异步I/O操作时需要对该结构体的hEvent进行设置
OVERLAPPED oRead = { 0 };
oRead.hEvent = CreateEvent(nullptr, TRUE, FALSE, L"ReadEvent");
ReadFile(hFile, bReadBuf, 100, nullptr, &oRead);
HANDLE WINAPI CreateEvent(
_In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,
//一个指向SECURITY_ATTRIBUTES结构的指针,确定返回的句柄是否可被子进程继承。如果lpEventAttributes是NULL,此句柄不能被继承
_In_ BOOL bManualReset,
//指定将事件对象创建成手动复原还是自动复原。如果是TRUE,那么必须用ResetEvent函数来手工将事件的状态复原到无信号状态。如果设置为FALSE,当一个等待线程被释放以后,系统将会自动将事件状态复原为无信号状态
_In_ BOOL bInitialState,
//指定事件对象的初始状态。如果为TRUE,初始状态为有信号状态;否则为无信号状态
_In_opt_ LPCTSTR lpName
//指定事件的对象的名称
);
简单的事例
int main()
{
HANDLE hFile = CreateFileW(L"demo.txt", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, nullptr);
if(hFile != INVALID_HANDLE_VALUE)
{
//Read
BYTE bReadBuf[100] = { 0 };
OVERLAPPED oRead = { 0 };
oRead.hEvent = CreateEvent(nullptr, TRUE, FALSE, L"ReadEvent");
ReadFile(hFile, bReadBuf, 100, nullptr, &oRead);
//Write
BYTE bWriteBuf[10] = { 0 };
OVERLAPPED oWrite = { 0 };
oWrite.hEvent = CreateEvent(nullptr, TRUE, FALSE, L"WriteEvent");
WriteFile(hFile, bWriteBuf, 10, nullptr, &oWrite);
//do something
HANDLE hOverLapped[2] = { 0 };
hOverLapped[0] = oRead.hEvent;
hOverLapped[1] = oWrite.hEvent;
while (true)
{
DWORD dwCase = WaitForMultipleObjects(2, hOverLapped, FALSE, INFINITE);
switch (dwCase - WAIT_OBJECT_0)
{
case 0:
//read
MessageBox(nullptr, L"Read", L"Read", MB_OK);
break;
case 1:
//write
MessageBox(nullptr, L"Write", L"Write", MB_OK);
break;
default: break;
}
}
}
return 0;
}