NULL);// 2. 文件读取PMYOVERLAPPED pol = new MYOVERLAPPED{};pol-

时间:2021-12-26 04:05:48

标签:Windows;异步;IO;

当我们对文件进行读写时,线程本该是梗阻的,即线程在期待读写操纵的结束,这种方法称为同步I/O。Windows在系统层为我们供给了一种高效的机制——异步IO
异步IO供给了这样一种成果:当你读取文件时,读取函数会立刻返回,读取任务转交给系统底层自动措置惩罚惩罚,,这样文件的读取操纵就不会梗阻线程。IO操纵完成时,由系统发出完成通知。

介绍三种完成通知:
1.直接期待句柄(文件期待东西)
2.期待OVERLAPPED中的hEvent句柄(期待事件东西)
3.异步挪用(APC挪用)

主要函数:CreateFile();ReadFile();WriteFile();
数据成员:OVERLAPPED布局体。

一个句柄如果是以异步IO的方法打开,那这个句柄就具有了两个特性
1.文件变为可期待的东西(即具有激发态和非激发态)
2.文件指针掉效(需要通过OVERLAPPED布局体中的的Offect暗示读取或写入的位置,而不能用SetFilePointer()这样的函数。)

代码实例:(VS2015控制台)
筹备:Debug目录下创建123.exe并生存数据

1.直接期待句柄 #include "stdafx.h" #include <windows.h> typedef struct _MYOVERLAPPED{ OVERLAPPED ol; HANDLE hFile; PBYTE pBuf; int nIndex; }MYOVERLAPPED,*PMYOVERLAPPED; DWORD WINAPI ThreadProc(LPVOID lParam) { PMYOVERLAPPED pol = (PMYOVERLAPPED)lParam; WaitForSingleObject(pol->hFile, INFINITE); for (int i=0;i<10;i++) { printf("%d:%d \n", pol->nIndex,pol->pBuf[i]); } printf("读完了!\n"); return 0; } int main() { // 1. 异步IO符号 // 有了这个符号 该文件就变为可期待的内查东西 // 后面的read write函数就变为非梗阻的 HANDLE hFile = CreateFile(L"123.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED, NULL); // 2. 文件读取 PMYOVERLAPPED pol = new MYOVERLAPPED{}; pol->ol.Offset = 0x0;// 从偏移0x100这个位置开始读 // pol->hEvent == NULL; 系统读取完成后,会把我的hFile变为有信号状态 pol->hFile = hFile; pol->pBuf = new BYTE[0x1000]{}; pol->nIndex =1; ReadFile(hFile, pol->pBuf, 0x1000, NULL,//实际读取的个数,由OVERLAPPED布局体指定 (LPOVERLAPPED)pol); HANDLE hThread = CreateThread(NULL, NULL, ThreadProc, pol, NULL, NULL); PMYOVERLAPPED pol2 = new MYOVERLAPPED{}; pol2->ol.Offset = 0x0;// 从偏移0x100这个位置开始读 // pol->hEvent == NULL; 系统读取完成后,会把我的hFile变为有信号状态 pol2->hFile = hFile; pol2->pBuf = new BYTE[0x1000]{}; pol2->nIndex = 2; ReadFile(hFile, pol2->pBuf, 0x1000, NULL,//实际读取的个数,由OVERLAPPED布局体指定 (LPOVERLAPPED)pol2); HANDLE hThread2 = CreateThread(NULL, NULL, ThreadProc, pol2, NULL, NULL); // ......干其他事 WaitForSingleObject(hThread, INFINITE); WaitForSingleObject(hThread2, INFINITE); return 0; } 2.期待事件东西 #include "stdafx.h" #include <windows.h> typedef struct _MYOVERLAPPED { OVERLAPPED ol; HANDLE hFile; PBYTE pBuf; int nIndex; }MYOVERLAPPED, *PMYOVERLAPPED; DWORD WINAPI ThreadProc(LPVOID lParam) { PMYOVERLAPPED pol = (PMYOVERLAPPED)lParam; printf("开始期待......\n"); WaitForSingleObject(pol->ol.hEvent, INFINITE); for (int i = 0; i < 10; i++) { printf("%d:%02x \n", pol->nIndex, pol->pBuf[i]); } printf("读完了!\n"); return 0; } int main() { // 1. 异步IO符号 // 有了这个符号 该文件就变为可期待的内查东西 // 后面的read write函数就变为非梗阻的 HANDLE hFile = CreateFile(L"..\\Debug\\123.exe", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); // 2. 文件读取 PMYOVERLAPPED pol = new MYOVERLAPPED{}; pol->ol.Offset = 0x100;// 从偏移0x100这个位置开始读 pol->ol.hEvent = CreateEvent(NULL,NULL,FALSE,NULL); //系统读取完成后,会把我的hFile变为有信号状态 pol->hFile = hFile;// 被无视 pol->pBuf = new BYTE[0x1000]{}; pol->nIndex = 1; ReadFile(hFile, pol->pBuf, 0x1000, NULL,//实际读取的个数,由OVERLAPPED布局体指定 (LPOVERLAPPED)pol); HANDLE hThread = CreateThread(NULL, NULL, ThreadProc, pol, NULL, NULL); PMYOVERLAPPED pol2 = new MYOVERLAPPED{}; pol2->ol.Offset = 0x200;// 从偏移0x100这个位置开始读 pol2->ol.hEvent = CreateEvent(NULL, NULL, FALSE, NULL); //系统读取完成后,会把我的hFile变为有信号状态 pol2->hFile = hFile;// 被无视 pol2->pBuf = new BYTE[0x1000]{}; pol2->nIndex = 2; ReadFile(hFile, pol2->pBuf, 0x1000, NULL,//实际读取的个数,由OVERLAPPED布局体指定 (LPOVERLAPPED)pol2); HANDLE hThread2 = CreateThread(NULL, NULL, ThreadProc, pol2, NULL, NULL); // ......干其他事 WaitForSingleObject(hThread, INFINITE); WaitForSingleObject(hThread2, INFINITE); return 0; } 3.异步挪用(APC挪用) 异步挪用供给了这样一个机制:你可以在读取文件或者写入文件的时候,供给一个回调函数,当读写任务完成时,就会挪用这个回调函数。 #include "stdafx.h" #include <windows.h> typedef struct _MYOVERLAPPED { OVERLAPPED ol; HANDLE hFile; PBYTE pBuf; int nIndex; }MYOVERLAPPED, *PMYOVERLAPPED; // 提交任务的线程措置惩罚惩罚,其他线程看着 VOID CALLBACK FileIOCompletionRoutine( _In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfered, _Inout_ LPOVERLAPPED lpOverlapped ) { PMYOVERLAPPED pol = (PMYOVERLAPPED)lpOverlapped; for (int i = 0; i < 10; i++) { printf("%d:%02x \n", pol->nIndex, pol->pBuf[i]); } printf("读完了!\n"); } int main() { // 1. 异步IO符号 // 有了这个符号 该文件就变为可期待的内查东西 // 后面的read write函数就变为非梗阻的 HANDLE hFile = CreateFile(L"..\\Debug\\123.exe", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); // 2. 文件读取 PMYOVERLAPPED pol = new MYOVERLAPPED{}; pol->ol.Offset = 0x100;// 从偏移0x100这个位置开始读 // hEvent被无视 hFile也被无视 //pol->ol.hEvent = CreateEvent(NULL, NULL, FALSE, NULL); //系统读取完成后,会把我的hFile变为有信号状态 pol->hFile = hFile;// 被无视 pol->pBuf = new BYTE[0x1000]{}; pol->nIndex = 1; ReadFileEx(hFile, pol->pBuf, 0x1000, (LPOVERLAPPED)pol, FileIOCompletionRoutine);// 完成后直接挪用该回调函数,不用期待文件句柄/事件东西 PMYOVERLAPPED pol2 = new MYOVERLAPPED{}; pol2->ol.Offset = 0x200;// 从偏移0x100这个位置开始读 //pol2->ol.hEvent = CreateEvent(NULL, NULL, FALSE, NULL); //系统读取完成后,会把我的hFile变为有信号状态 //pol2->hFile = hFile;// 被无视 pol2->pBuf = new BYTE[0x1000]{}; pol2->nIndex = 2; ReadFileEx(hFile, pol2->pBuf, 0x1000, (LPOVERLAPPED)pol2, FileIOCompletionRoutine); // FileIOCompletionRoutine有系统挪用 // 哪个线程执行该函数呢 // 哪个线程read/write 哪个线程执行 // ......干其他事 // 忙完了 想起来还有两个函数等着我呢 // CPU检测到当前线程的APC行列队伍里有函数需要执行 // 就去执行该函数,执行完返回 // 只有当第2个参数是TRUE才去执行 SleepEx(200, TRUE); // WaitForSingleObjectEx() return 0; }

Windows异步I/O详解

标签:Windows;异步;IO;