下面是创建IO完成端口的函数
//创建一个IO完成端口 HANDLE CreateNewCompletionPort(DWORD NumberOfConcurrentThreads ) { return ( CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL,0, NumberOfConcurrentThreads )); } //将设备与IO端口关联起来 BOOL AssociateDeviceWithCompletionPort(HANDLE hCompletionPort, HANDLE hDevice, DWORD dwCompletionKey) { //参数2不为NULL,那么参数4忽略 HANDLE h = CreateIoCompletionPort(hDevice, hCompletionPort,dwCompletionKey,0); return (h == hCompletionPort); }
IO完成端口有5个基础的数据结构:
1 设备列表 包含关联的设备
2 IO完成队列(先入先出)IO请求完成,或者Post一个IO完成请求
3 以释放线程 (后入先出)从等待线程唤醒处理IO完成请求,或者暂停的线程被唤醒
4 以等待线程 已经释放的线程如果等待了,那么进入等待线程列表
5 以暂停线程 释放的被暂停
向设备发出IO请求,但不把该项的已完成的IO请求添加到IO队列去,是可以的,具体方法是:
Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE,NULL);
Overlapped.hEvent = (HANDLE) ((DWOR_PTR)Overlapped.hEvent | 1 );
ReadFile(...,&Overlapped);
关闭这个事件句柄时不要忘记最低位清掉
CloseHandle((Handle)((DWORD_PTR)Overlapped.hEvent & ~1) );
#include <windows.h> #include <stdio.h> #include <process.h> #define COMPLETION_KEY_READ 1 #define COMPLETION_KEY_WRITE 2 typedef struct MyData : public OVERLAPPED { LPTSTR m_lpBuffer; LONG m_bufferSize; MyData() { Internal = InternalHigh = 0 ; Offset = OffsetHigh = 0; this->hEvent = NULL; } }MYDATA; long g_fileSize = 0; LONG lReadcount = 0; LONG lWritecount = 0; HANDLE g_hFileRead,g_hFileWrite; MYDATA data1,data2; unsigned WINAPI ThreadFunc(LPVOID lp) { HANDLE hIO = (HANDLE)lp; ULONG_PTR comKey = 0; LPOVERLAPPED plov = NULL; MYDATA* pData = NULL; long filereadSize = 0; DWORD dw; const long bufferSize = 4*1024; while(lReadcount > 0 || lWritecount > 0 ) { BOOL bok = GetQueuedCompletionStatus(hIO, &dw,&comKey,(LPOVERLAPPED*) &pData, INFINITE); switch(comKey) { case COMPLETION_KEY_READ: lReadcount--; WriteFile(g_hFileWrite, pData->m_lpBuffer, bufferSize, &dw, pData); lWritecount++; break; case COMPLETION_KEY_WRITE: lWritecount--; if(filereadSize >= g_fileSize) break; lReadcount++; pData->Offset = filereadSize; pData->OffsetHigh = 0; ReadFile(g_hFileRead,pData->m_lpBuffer, bufferSize, &dw, pData); filereadSize += bufferSize; break; default: break; } } CloseHandle(g_hFileRead); CloseHandle(g_hFileWrite); HANDLE hFile = CreateFile(L"2.txt", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); LARGE_INTEGER ll; ll.QuadPart = g_fileSize; SetFilePointerEx(hFile,ll,NULL,FILE_BEGIN); SetEndOfFile(hFile); return 0; } int main() { HANDLE hIoCp = CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0); g_hFileRead = CreateFile(TEXT("1.txt"),GENERIC_ALL,0,NULL, OPEN_ALWAYS,FILE_FLAG_OVERLAPPED, NULL); g_hFileWrite = CreateFile(TEXT("2.txt"), GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED, NULL); LARGE_INTEGER lagerFile; GetFileSizeEx(g_hFileRead, &lagerFile); g_fileSize = lagerFile.QuadPart; if(CreateIoCompletionPort(g_hFileRead, hIoCp, COMPLETION_KEY_READ, 0) != hIoCp) { return GetLastError(); } if (CreateIoCompletionPort(g_hFileWrite, hIoCp, COMPLETION_KEY_WRITE, 0) != hIoCp) { return GetLastError(); } data1.m_bufferSize = 4 * 1024; data1.m_lpBuffer =(LPTSTR) VirtualAlloc(NULL, data1.m_bufferSize, MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE); data2.m_bufferSize = data1.m_bufferSize; data2.m_lpBuffer = (LPTSTR) VirtualAlloc(NULL, data2.m_bufferSize, MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE); PostQueuedCompletionStatus(hIoCp, 0, COMPLETION_KEY_WRITE, &data1); PostQueuedCompletionStatus(hIoCp, 0, COMPLETION_KEY_WRITE, &data2); lWritecount = 2; HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, hIoCp, 0, NULL); WaitForSingleObject(hThread,INFINITE); CloseHandle(hIoCp); system("pause"); // getchar(); return 0; }