Windows 异步IO操作(二)
异步IO操作可以的四种提醒方式:
使用设备内核对象
- 在上节课中, 我们使用了
设备内核对象来进行异步文件操作的提醒 - 传送门
- 在上节课中, 我们使用了
- 使用事件内核对象
- 可提醒IO
- IO完成端口
事件内核对象提醒
使用时间内核对象提醒, 可以分为以下几步:
- 发送请求
- 做自己的事情
- 判断请求是否完成
// 事件内核对象的小例子
#include <Windows.h>
int main()
{
HANDLE hFile = CreateFile(TEXT("Demo.txt"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_FLAG_OVERLAPPED,
NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
// Read
OVERLAPPED oRead = {0};
oRead.Offset = 0;
// 创建一个事件内核对象
oRead.hEvent = CreateEvent(NULL,
TRUE,
FALSE,
TEXT("ReadEvent")); // 这个名称比较重要 我们知道名称就可以得到这个事件内核对象
BYTE bReadBuf[100] = {0};
// 异步读取文件
ReadFile(hFile, bReadBuf, sizeof(bReadBuf), NULL, &oRead);
// Write
OVERLAPPED oWrite = {0};
oWrite.Offset = 0;
// 创建一个事件内核对象
oWrite.hEvent = CreateEvent(NULL,
TRUE,
FALSE,
TEXT("WriteEvent")); // 这个名称比较重要 我们知道名称就可以得到这个事件内核对象
BYTE bWriteBuf[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// 异步读取文件
WriteFile(hFile, bWriteBuf, sizeof(bWriteBuf), NULL, &oWrite);
// 还可以有其他操作
// 模拟其他线程操作
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:
// 读完成
break;
case 1:
// 写完成
break;
}
}
}
else
{
// GetLastError()
}
return 0;
}事件内核对象可用于程序和程序之间数据的共享和互通
可提醒IO
使用可提醒IO, 可以分为如下几步:
- 发送请求
- 操作完成后, 操作系统提醒我
APC机制
我们都知道, 我们的进程是工厂, 线程是工人.
在线程中, 有APC机制.
APC机制
- 当
线程"闲置"(为可提醒状态下)的时候 - 线程去执行
APC列表中的事情(自动执行的)
注意:
MessageBox等函数会 阻塞 我们的线程, 但是此时的线程是不可提醒的.
通过 SleepEx, WaitForSingleObjectEx, WaitForMultipleObjectEx, SingalObjectAndWait, MsgWaitForMultipleObjectsEx 可设置线程的 可提醒状态.示例
#include <Windows.h>
VOID CALLBACK FileIOCommpletionRoutineRead(
_In_ DWORD dwErrorCode,
_In_ DWORD dwNumberOfBytesTransfered,
_Inout_ LPOVERLAPPED lpOverlapped
)
{
MessageBox(NULL,
TEXT("Read Over!"),
TEXT("Read Over!"),
MB_OK | MB_ICONINFORMATION);
}
int main()
{
HANDLE hFile = CreateFile(TEXT("Demo.txt"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_FLAG_OVERLAPPED,
NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
CONST UINT unLen = 255;
// Read
OVERLAPPED oRead = {0};
oRead.Offset = 0;
BYTE bReadBuf[unLen] = {0};
// 异步读取文件 通过可提醒IO
ReadFileEx(hFile,
bReadBuf,
unLen,
&oRead,
FileIOCommpletionRoutineRead);
// 设置线程为可提醒状态
// SleepEx
// Wait.... 函数
// 很重要, 不设置就不会调用APC事件列表
SleepEx(100, TRUE);
// 可以干其他的事情了....
}
else
{
// GetLastError()
}
return 0;
}不建议使用可提醒IO, 因为回调函数中可操作的数据太少
如果将ReadBuf做成全局, 那么会影响我们的文件结构逻辑
未完待续...
如有错误,请提出指正!谢谢.
本文由 花心胡萝卜 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: 2017-05-30 at 02:15 pm