异步IO
使用CreateFile打开大文件或者其它设备的时候,如果是用的同步IO模式,就有可能会造成阻塞,因此也就有了异步IO模式
异步IO机制
在调用openFile的时候,就会向操作系统的设备发送请求,openFile会直接返回;
操作系统看到这个请求,会进行操作
当操作完成之后,会发给程序一个通知做很多的操作的时候,都仅仅是发送个请求,直接返回,程序会做自己的事情,操作系统做实际操作,等待操作完成后,直接去拿,使得程序无须等待,在特定的一些情况下的使用
进程、线程与阻塞
进程
是当前运行程序的空间(主要做存储)
线程
是实际运行的单位(工作单位)
操作阻塞
指的是线程被停止、阻塞
进程是工厂,是一个空间,一块地盘,而线程是在里面的工人,工人可以有很多,也就是多线程
多线程
通过系统线程帮我们完成
异步操作——CreateFile
在之前的文章中,对CreateFile进行了浅析,参数dwFlagsAndAttributes的属性值中,有这么一个值:FILE_FLAG_OVERLAPPED,此时此文件或设备被打开或创建,用于异步 I/O
CreateFile的返回值(HANDLE)接下来的操作(Read和Write)都会以异步的方式进行
重要的一个结构体——OVERLAPPED结构体
原型
“`
typedef struct _OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
};
PVOID Pointer;
};
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
>>ULONG_PTR Internal
>>>保存错误码、当前操作是否完成
>
>>ULONG_PTR InternalHigh
>>>用来保存传输成功的字节数
>>>>
>
>>DWORD offset
>>DWORD offsetHigt
>>>两个DWORD组成一个64位数值
>>>
>>>以异步操作的方式打开设备时,设备对象并不会保存以前的位置,所以就必须告诉它从哪个位置开始操作
>>>>ReadFile与WriteFile中的参数中的实际读取/写入参数,在同步的时候是有用的,但是在异步的时候没用,因为程序是直接返回。所以需要用OVERLAPPED结构体中的InternalHigh来判断实际写入/读取的字节数
>
>>>天生带有文件分割的功能,因为可以设置从哪开始!
>>>
>>>同步的时候一般都设为nullptr
>
>>HANDLE hEvent
>>>事件内核对象,操作系统通知程序的一种方式
>
简单实例
#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 };//开始读取位置也设为0了,如果需要,还可以在下面程序中修改
overLapped.Offset = 100; // 从100开始读
BYTE bBuffer[MAXBYTE] = { 0 };
BOOL bRet = ReadFile(hFile,
bBuffer,
MAXBYTE,
NULL,
&overLapped);//实际读取的字符设为NULL,因为它已经没啥用了
DWORD dwRet = GetLastError();
if (bRet && dwRet == ERROR_IO_PENDING)
{
// 请求发送成功
// 写自己的逻辑,
//用途:一个用户请求来了,需要马上处理的,就可以在这边进行操作
// ...
WaitForSingleObject(hFile, INFINITE); // 阻塞到请求完成
// 演示用, 正式环境请不要使用此方法,会按条件阻塞,好处是可以在上面写自己的逻辑
}
CloseHandle(hFile);
return 0;
}
“`
WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds)
Windows API函数。当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。
参数
hHandle
[in],对象句柄。可以指定一系列的对象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等
dwMilliseconds
[in],定时时间间隔,单位为milliseconds(毫秒)。
如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。
如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。
如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。
参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。