异步I/O之文件
Posted _xiaohaige
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异步I/O之文件相关的知识,希望对你有一定的参考价值。
一、概念:
1.1、打开设备的操作会向操作系统发送请求,CreateFile函数会直接返回,而不会去等待操作完成。
1.2、此时操作系统会发现这个请求,然后操作系统会来进行实际的操作,当操作完成之后,
1.3、会设置一些标志,也就是通知。
1.4、在操作系统进行实际操作的时候,我可以来做一些想要做的操作,当通知来了的时候,I/O完成。
1.5、这使得我们无须等待CreateFile操作的完成,就能进行其他的操作。
1.6、为什么会产生阻塞?
1.6.1、进程:程序运行的一块空间,存储(一个)。
1.6.2、线程:程序实际运行的单位,工作,和 CPU 打交道的是线程(多个)。
1.6.3、WaitForSingleObject(hFile, INFINITE) //阻塞,等待操作完成。
1.7、OVERLAPPED结构体:
1.7.1、 typedef struct _OVERLAPPED { ULONG_PTR Internal; ULONG_PTR InternalHigh; union { struct { DWORD Offset; //64位的偏移量,低位。表示从哪里开始。 DWORD OffsetHigh; //高位。表示结束的位置。 }; PVOID Pointer; }; HANDLE hEvent; } OVERLAPPED, *LPOVERLAPPED;
1.8、在进行一步I/O操作的时候有四种可用的提醒操作完成的方式:
1.8.1、使用设备内核对象。
if (!bRet && GetLastError() == ERROR_IO_PENDING) { std::cout << "正在等待IO完成。。。。。" << std::endl; WaitForSingleObject(hFile, INFINITE); //使用这个函数进行阻塞,等待I/O完成。 }
1.8.2、使用事件内核对象。
1.8.2.1、唯一的只有一个。
1.8.2.2、所谓的内核对象都是独立于我们的程序的,它们是属于操作系统的。
char readBuffer[MAXBYTE] = { 0 }; OVERLAPPED readOV = { 0 }; readOV.Offset = 0; readOV.hEvent = CreateEvent(nullptr, true, false, _T("readEvent")); //创建了一个事件内核对象。 ReadFile(hFile, readBuffer, MAXBYTE, nullptr, &readOV); //会直接发送一个请求,然后继续往下执行。 char writeBuffer[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; OVERLAPPED writeOV = { 0 }; writeOV.Offset = 0; writeOV.hEvent = CreateEvent(nullptr, true, false, _T("writeEvent")); //创建了一个事件内核对象。 WriteFile(hFile, writeBuffer, strlen(writeBuffer), nullptr, &writeOV); //会直接发送一个请求,然后继续往下执行。 //其他线程: HANDLE hOverLapped[2] = { 0 }; hOverLapped[0] = readOV.hEvent; hOverLapped[1] = writeOV.hEvent; while (true) { DWORD dwCase = WaitForMultipleObjects(2, hOverLapped, FALSE, INFINITE);//还是需要这个函数进行等待。 switch(dwCase - WAIT_OBJECT_0) { case 0: //读完成 std::cout << "read is access" << std::endl; break; case 1: //写完成 std::cout << "write is access" << std::endl; break; } }
1.8.3、可提醒I/O。
1.8.3.1、发送请求 -> 做自己的事情 -> 判断请求是否完成。 异步I/O
1.8.3.2、发送请求 -> 完成后,操作系统提醒我。这种方式明显的比上面的方式要好。当然这样能不能做到呢?
1.8.3.3、可提醒I/O操作可以完成:
APC机制:工厂(进程) -> 工人(线程):当线程闲的时候(前提) ->APC列表中的事情(自动的执行)(线程为可提醒状态下)
1.8.3.4、可提醒I/O就是基于APC机制来做的异步I/O操作。但并不是太好用。
1.8.3.5、虽然说可提醒I/O并不好用,但是APC机制还是很好用的。
1.8.3.6、当我们的线程处在可提醒状态的话呢,线程就会去执行APC的回调函数。
1.8.4、I/O完成端口。
1.8.4.1、概述:最为方便,也是最为科学的一种方式。
以上是关于异步I/O之文件的主要内容,如果未能解决你的问题,请参考以下文章