Poedu

xiaoxiao2021-02-28  95

异步IO

使用异步IO的四种提醒方式

1.使用设备内核对象进行提醒

进行异步文件操作的提醒

2.使用事件内核对象提醒

提醒同步以及交互,是一种完全不同的的提醒

3.可提醒IO

不可跨线程的

4.I/O完成端口

使用最广泛

使用事件内核对象提醒

示例

#include<windows.h> int main() { HANDLE hFile =CreateFile(TEXT("demo.txt",GENERIC_READ|GENERAIC_WRITE,FILE_SHARE,nullptr,OPEN_ALWAYS,FILE_FALG_OVERLAPPED,NULL); if(hFile != INVALID_HANDLE_VALUE) { //read BYTE bReadBuffer[100]={0}; OVERLAPPED oRead ={0}; oRead.Offset=0; oRead.hEvent = CreateEvent(nullptr,TRUE,FALSE,TEXT("ReadEvent"));//事件内核对象,是独立于程序之外的,属于操作系统的,通过name在各个程序中使用 ReadFile(hFile,bReadBuffer,sizeof(bReadBuffer),nullptr,&oRead); //write BYTE bWriteBuffer[10]={0}; OVERLAPPED oWrite ={0}; oWrite.Offset=0; oWrite.hEvent = CreateEvent(nullptr,TRUE,FALSE,TEXT("WriteEvent"));//事件内核对象,是独立于程序之外的,属于操作系统的,通过name在各个程序中使用 WriteFile(hFile,bWriteBuffer,sizeof(bWriteBuffer),nullptr,&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 } }

程序领空与系统领空

系统领空是所有程序共用的,事件内核对象存在于系统领空,那么程序与程序之间的交互就可以通过事件内核对象,也可以通过事件内核对象中的对象来判断状态

可提醒IO

事件内核对象提醒:

发送请求 做自己的事情 判断请求是否完成

可提醒IO:

发送请求 完成后,操作系统提醒我

APC机制 进程是工厂,线程是工人,在线程的内部,它有一个机制:APC

当工人闲的时候(前提),来做APC列表中的事情

当线程空闲的时候(线程为可提醒状态下),自动执行APC列表中的事情

比如:MessageBox会导致线程阻塞,当这个线程阻塞的时候,看上去线程闲下来了,但是并不是可提醒状态,在windows中,只有Wait函数、Sleep函数才能真正的“闲”下来

相当于一个不定时的定时器,APC不确定啥时候会被触发,但是只要触发就会去做事情

提醒IO就是依托于APC来做的

示例

#include<windows.h> int main() { HANDLE hFile =CreateFile(TEXT("demo.txt",GENERIC_READ|GENERAIC_WRITE,FILE_SHARE,nullptr,OPEN_ALWAYS,FILE_FLAG_OVERLAPPED,NULL)); if(hFile != INVALID_HANDLE_VALUE) { CONST UINT unLen = 255; // Read OVERLAPPED oRead = {0};//此时里面的东西都不用设置,Offset可以设置,但是Event不能设置 oRead.Offset = 0; BYTE bReadBuf[unLen] = {0}; // 异步读取文件 通过可提醒IO ReadFileEx(hFile, bReadBuf, unLen, &oRead,FileIOCommpletionRoutineRead); // 可以使得线程为可提醒状态的函数 // SleepEx // Wait.... 函数 SleepEx(100, TRUE);//BOOL值代表,当SleepEx被调用的时候,是否把自己设置为空闲状态,不设置为TRUE的时候,也就相当于阻塞但非可提醒状态,此时APC不会被调用,所以这个BOOL值很重要 } else { //GetLastError } }

可提醒不是那么好用:

回调函数参数太少,作用有限,可通过全局来传入参数,但是逻辑会混乱

完成端口机制

操作异步IO最为方便、科学的方式

以上三种都是一个线程之内来做的事情,可提醒IO可以让别的线程来做这件事情,但是做起来较为麻烦,使用的是串行模型来进行异步IO操作

异步IO操作最适合的是并行模式,是多线程。

windows是多进程的

但是在单核时代,是模拟出来的多进程,只是CPU运行速度快,我们没感觉而已

多核下,每个核都可以运行一个线程(无切换), 也可以进行线程切换

多进程

如果进程只有一个线程,那么一个程序只能做一件事情,如果需要做两件事情,那么就需要两个进程,但是,两个进程都会有一个内核对象,如果两个进程进行交互的话,那么会耗费大量的资源,所以在进程之下设计了线程

多线程

线程之间的切换也会耗费资源,只是比线程之间切换要好点。核心数增加之后,并行模式开始流行起来

完成端口是天生的并行模式,使用它来异步操作大文件的时候会更快

未完待续…

如有错误,烦请指出..

转载请注明原文地址: https://www.6miu.com/read-65368.html

最新回复(0)