Windows IO异步操作
异步IO机制
当我们使用CreateFile打开大文件或者其他设备的时候
可能会造成阻塞
所以我们Windows设计了异步IO机制.
- 当我们利用
CreteFile的时候,会向设备发送一个请求 - 发送请求完成后,
CreateFile会直接返回 - 操作系统得到请求后, 完成实际的
打开操作 - 当操作系统完成请求后, 会发送一个
通知 CreateFile接受到通知后, 进行设备操作.- 期间, 可以进行其他的操作
画一个简单的图来表示一下同步和异步: 
为什么会产生阻塞
我们都知道, Windows下每个程序都有一个进程 进程是我们程序运行起来后的空间, 它起到存储数据的作用 线程则是我们实际运行进行操作的单位, 它是用来工作的, 和CPU打交道
进程相当于工厂, 线程相当于工人.
工厂可以有多个工人, 这种情况我们称之为多线程
阻塞, 就是我们的工作线程由于忙而被等待了.
可以通过多线程达到异步的操作
也可以通过Windows API的设置来达到异步的操作
WindowsAPI实现异步
HANDLE hFile = CreateFile(TEXT("Test.txt"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_FLAG_OVERLAPPED, // 重要属性 该属性表示异步操作设备
NULL);当我们的 CreateFile 以异步方式打开后, 它返回的 hFile 的读写操作也将变成异步
OVERLAPPED结构体
原型:
typedef struct _OVERLAPPED {
ULONG_PTR Internal; // 保存我们请求的错误码
ULONG_PTR InternalHigh; // 保存我们传输成功的字节数
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
};
PVOID Pointer;
}; // 64位的偏移量 一个低位 一个高位
HANDLE hEvent; // 事件内核对象
} OVERLAPPED, *LPOVERLAPPED;Internal
- 表示操作的
错误代码 - 可通过它进行一些状态的判断
- 会被重置和修改
InternalHigh
- 主要用于在ReadFile或者WriteFile的时候来获取我们成功操作的字节数
Pointer
- 以异步方式打开设备的时候, 并不会保存我们设备的位置
- 所以这个
位置非常重要 - 它代表了我们要对
设备操作的位置
hEvent
- 让操作系统
以事件方式通知我们设备已经操作完成 可以存放其他的对象
- 因为
HANDLE是void*类型
- 因为
简单示例
#include <Windows.h>
#include <tchar.h>
int main()
{
HANDLE hFile = CreateFile(TEXT("Test.txt"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_FLAG_OVERLAPPED,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
return -1;
OVERLAPPED overLapped = { 0 };
overLapped.Offset = 100; // 从100开始读
BYTE bBuffer[MAXBYTE] = { 0 };
BOOL bRet = ReadFile(hFile,
bBuffer,
MAXBYTE,
NULL,
&overLapped);
DWORD dwRet = GetLastError();
if (bRet && dwRet == ERROR_IO_PENDING)
{
// 请求发送成功
// 可以搞一些其他事情.
// ...
WaitForSingleObject(hFile, INFINITE); // 阻塞到请求完成
// 演示用, 正式环境请不要使用此方法
}
CloseHandle(hFile);
return 0;
}未完待续...
如有错误,请提出指正!谢谢.
本文由 花心胡萝卜 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: 2017-05-20 at 10:48 am