I/O完成端口
来源:互联网 发布:silk labo 知乎 编辑:程序博客网 时间:2024/04/29 22:56
I/O完成端口存在5个数据结构
1.设备列表 存放:设备句柄和I/O key
2.I/O完成队列 存放:I/O完成记录 先进先出
3.等待线程队列 存放:等待处理I/O完成记录 后进先出
4.已释放线程列表 存放:正在处理I/O完成记录的线程
5.已暂停线程列表 存放:挂起的线程
系统将异步I/O请求函数中请求完成后放入2中,检查4中正在运行的线程数是否低于并行数,是则唤醒3中线程。
PostQueuedCompletionStatus 用来将一个已完成的I/O通知追加到I/O完成端口的队列中。
如2中最初放入W1,W2,W3,W4 4个I/O完成记录
3中调用GetQueuedCompletionStatus 3中线程为T1,T2 取出W1,W2 处理方式是Readfile,T2->W1,T1->W2,处理完2中变为W3,W4,R1,R2 3中变为T1,T2 //如果CreateIoCompletionPort中最后并行数设为2
3中调用GetQueuedCompletionStatus 取出W3,W4 处理方式是Readfile,T2->W3,T1->W4 处理完2中变为R1,R2,R3,R4 3中变为T2,T1 //哪个线程先等待则先进入3中
3中调用GetQueuedCompletionStatus 取出R1,R2 处理方式是Writefile,T1->R1,T2->R2 处理完2中变为R3,R4,W5,W6 3中变为T2,T1
....
//EnsureCleanup.h/******************************************************************************Module: EnsureCleanup.hNotices: Copyright (c) 2007 Jeffrey Richter & Christophe NasarrePurpose: These classes ensure object cleanup when an object goes out of scope. See Appendix A.******************************************************************************/#pragma once // Include this header file once per compilation unit///////////////////////////////////////////////////////////////////////////////#include <Windows.h>///////////////////////////////////////////////////////////////////////////////// Data type representing the address of the object's cleanup function.// I used UINT_PTR so that this class works properly in 64-bit Windows.typedef VOID (WINAPI* PFNENSURECLEANUP)(UINT_PTR);///////////////////////////////////////////////////////////////////////////////// Each template instantiation requires a data type, address of cleanup // function, and a value that indicates an invalid value.template<class TYPE, PFNENSURECLEANUP pfn, UINT_PTR tInvalid = NULL> class CEnsureCleanup {public: // Default constructor assumes an invalid value (nothing to cleanup) CEnsureCleanup() { m_t = tInvalid; } // This constructor sets the value to the specified value CEnsureCleanup(TYPE t) : m_t((UINT_PTR) t) { } // The destructor performs the cleanup. ~CEnsureCleanup() { Cleanup(); } // Helper methods to tell if the value represents a valid object or not.. BOOL IsValid() { return(m_t != tInvalid); } BOOL IsInvalid() { return(!IsValid()); } // Re-assigning the object forces the current object to be cleaned-up. TYPE operator=(TYPE t) { Cleanup(); m_t = (UINT_PTR) t; return(*this); } // Returns the value (supports both 32-bit and 64-bit Windows). operator TYPE() { return (TYPE) m_t; } // Cleanup the object if the value represents a valid object void Cleanup() { if (IsValid()) { // In 64-bit Windows, all parameters are 64-bits, // so no casting is required pfn(m_t); // Close the object. m_t = tInvalid; // We no longer represent a valid object. } } private: UINT_PTR m_t; // The member representing the object};///////////////////////////////////////////////////////////////////////////////// Macros to make it easier to declare instances of the template // class for specific data types.#define MakeCleanupClass(className, tData, pfnCleanup) \ typedef CEnsureCleanup<tData, (PFNENSURECLEANUP) pfnCleanup> className;#define MakeCleanupClassX(className, tData, pfnCleanup, tInvalid) \ typedef CEnsureCleanup<tData, (PFNENSURECLEANUP) pfnCleanup, \ (INT_PTR) tInvalid> className;///////////////////////////////////////////////////////////////////////////////// Instances of the template C++ class for common data types.MakeCleanupClass(CEnsureCloseHandle, HANDLE, CloseHandle);MakeCleanupClassX(CEnsureCloseFile, HANDLE, CloseHandle, INVALID_HANDLE_VALUE);MakeCleanupClass(CEnsureLocalFree, HLOCAL, LocalFree);MakeCleanupClass(CEnsureGlobalFree, HGLOBAL, GlobalFree);MakeCleanupClass(CEnsureRegCloseKey, HKEY, RegCloseKey);MakeCleanupClass(CEnsureCloseServiceHandle, SC_HANDLE, CloseServiceHandle);MakeCleanupClass(CEnsureCloseWindowStation, HWINSTA, CloseWindowStation);MakeCleanupClass(CEnsureCloseDesktop, HDESK, CloseDesktop);MakeCleanupClass(CEnsureUnmapViewOfFile, PVOID, UnmapViewOfFile);MakeCleanupClass(CEnsureFreeLibrary, HMODULE, FreeLibrary);///////////////////////////////////////////////////////////////////////////////// Special class for releasing a reserved region.// Special class is required because VirtualFree requires 3 parametersclass CEnsureReleaseRegion {public: CEnsureReleaseRegion(PVOID pv = NULL) : m_pv(pv) { } ~CEnsureReleaseRegion() { Cleanup(); } PVOID operator=(PVOID pv) { Cleanup(); m_pv = pv; return(m_pv); } operator PVOID() { return(m_pv); } void Cleanup() { if (m_pv != NULL) { VirtualFree(m_pv, 0, MEM_RELEASE); m_pv = NULL; } } private: PVOID m_pv;};///////////////////////////////////////////////////////////////////////////////// Special class for freeing a block from a heap// Special class is required because HeapFree requires 3 parametersclass CEnsureHeapFree {public: CEnsureHeapFree(PVOID pv = NULL, HANDLE hHeap = GetProcessHeap()) : m_pv(pv), m_hHeap(hHeap) { } ~CEnsureHeapFree() { Cleanup(); } PVOID operator=(PVOID pv) { Cleanup(); m_pv = pv; return(m_pv); } operator PVOID() { return(m_pv); } void Cleanup() { if (m_pv != NULL) { HeapFree(m_hHeap, 0, m_pv); m_pv = NULL; } } private: HANDLE m_hHeap; PVOID m_pv;};template <class TV, class TM>inline TV chROUNDDOWN(TV Value, TM Multiple) { return((Value / Multiple) * Multiple);}// This inline function rounds a value down to the nearest multipletemplate <class TV, class TM>inline TV chROUNDUP(TV Value, TM Multiple) { return(chROUNDDOWN(Value, Multiple) + (((Value % Multiple) > 0) ? Multiple : 0));}///////////////////////////////// End of File /////////////////////////////////
//IoCompletionPort.h/******************************************************************************Module: IOCP.hNotices: Copyright (c) 2007 Jeffrey Richter & Christophe NasarrePurpose: This class wraps an I/O Completion Port. See Appendix B.******************************************************************************/#pragma once // Include this header file once per compilation unit///////////////////////////////////////////////////////////////////////////////#include <Windows.h>#define chVERIFY#define chASSERT///////////////////////////////////////////////////////////////////////////////class CIOCP {public: CIOCP(int nMaxConcurrency = -1) { m_hIOCP = NULL; if (nMaxConcurrency != -1) (void) Create(nMaxConcurrency); } ~CIOCP() { if (m_hIOCP != NULL) chVERIFY(CloseHandle(m_hIOCP)); } BOOL Close() { BOOL bResult = CloseHandle(m_hIOCP); m_hIOCP = NULL; return(bResult); } BOOL Create(int nMaxConcurrency = 0) { m_hIOCP = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, nMaxConcurrency); chASSERT(m_hIOCP != NULL); return(m_hIOCP != NULL); } BOOL AssociateDevice(HANDLE hDevice, ULONG_PTR CompKey) { BOOL fOk = (CreateIoCompletionPort(hDevice, m_hIOCP, CompKey, 0) == m_hIOCP); chASSERT(fOk); return(fOk); } BOOL AssociateSocket(SOCKET hSocket, ULONG_PTR CompKey) { return(AssociateDevice((HANDLE) hSocket, CompKey)); } BOOL PostStatus(ULONG_PTR CompKey, DWORD dwNumBytes = 0, OVERLAPPED* po = NULL) { BOOL fOk = PostQueuedCompletionStatus(m_hIOCP, dwNumBytes, CompKey, po); chASSERT(fOk); return(fOk); } BOOL GetStatus(ULONG_PTR* pCompKey, PDWORD pdwNumBytes, OVERLAPPED** ppo, DWORD dwMilliseconds = INFINITE) { return(GetQueuedCompletionStatus(m_hIOCP, pdwNumBytes, pCompKey, ppo, dwMilliseconds)); }private: HANDLE m_hIOCP;};///////////////////////////////// End of File /////////////////////////////////
//main.cpp/******************************************************************************Module: FileCopy.cppNotices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre******************************************************************************/#include "IOCompletionPort.h" // See Appendix A.#include "EnsureCleanup.h" // See Appendix A.#include <WindowsX.h>// C RunTime Header Files#include <stdlib.h>#include <malloc.h>#include <memory.h>#include <tchar.h>#include <string>///////////////////////////////////////////////////////////////////////////////// Each I/O Request needs an OVERLAPPED structure and a data bufferclass CIOReq : public OVERLAPPED {public: CIOReq() { Internal = InternalHigh = 0; Offset = OffsetHigh = 0; hEvent = NULL; m_nBuffSize = 0; m_pvData = NULL; } ~CIOReq() { if (m_pvData != NULL) VirtualFree(m_pvData, 0, MEM_RELEASE); } BOOL AllocBuffer(SIZE_T nBuffSize) { m_nBuffSize = nBuffSize; m_pvData = VirtualAlloc(NULL, m_nBuffSize, MEM_COMMIT, PAGE_READWRITE); return(m_pvData != NULL); } BOOL Read(HANDLE hDevice, PLARGE_INTEGER pliOffset = NULL) { if (pliOffset != NULL) { Offset = pliOffset->LowPart; OffsetHigh = pliOffset->HighPart; } return(::ReadFile(hDevice, m_pvData, m_nBuffSize, NULL, this)); } BOOL Write(HANDLE hDevice, PLARGE_INTEGER pliOffset = NULL) { if (pliOffset != NULL) { Offset = pliOffset->LowPart; OffsetHigh = pliOffset->HighPart; } return(::WriteFile(hDevice, m_pvData, m_nBuffSize, NULL, this)); }private: SIZE_T m_nBuffSize; PVOID m_pvData;};/////////////////////////////////////////////////////////////////////////////////#define BUFFSIZE (64 * 1024) // The size of an I/O bufferDWORD BUFFSIZE = 0;#define MAX_PENDING_IO_REQS 4 // The maximum # of I/Os// The completion key values indicate the type of completed I/O.#define CK_READ 1#define CK_WRITE 2///////////////////////////////////////////////////////////////////////////////BOOL FileCopy(PCTSTR pszFileSrc, PCTSTR pszFileDst) { BOOL bOk = FALSE; // Assume file copy fails LARGE_INTEGER liFileSizeSrc = { 0 }, liFileSizeDst; try { { // Open the source file without buffering & get its size CEnsureCloseFile hFileSrc = CreateFile(pszFileSrc, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL); if (hFileSrc.IsInvalid()) goto leave; // Get the file's size GetFileSizeEx(hFileSrc, &liFileSizeSrc); // Nonbuffered I/O requires sector-sized transfers. // I'll use buffer-size transfers since it's easier to calculate. liFileSizeDst.QuadPart = chROUNDUP(liFileSizeSrc.QuadPart, BUFFSIZE); // Open the destination file without buffering & set its size CEnsureCloseFile hFileDst = CreateFile(pszFileDst, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, hFileSrc); if (hFileDst.IsInvalid()) goto leave; // File systems extend files synchronously. Extend the destination file // now so that I/Os execute asynchronously improving performance. SetFilePointerEx(hFileDst, liFileSizeDst, NULL, FILE_BEGIN); SetEndOfFile(hFileDst); // Create an I/O completion port and associate the files with it. CIOCP iocp(2);//并行数 iocp.AssociateDevice(hFileSrc, CK_READ); // Read from source file iocp.AssociateDevice(hFileDst, CK_WRITE); // Write to destination file // Initialize record-keeping variables CIOReq ior[MAX_PENDING_IO_REQS]; LARGE_INTEGER liNextReadOffset = { 0 }; int nReadsInProgress = 0; int nWritesInProgress = 0; // Prime the file copy engine by simulating that writes have completed. // This causes read operations to be issued. for (int nIOReq = 0; nIOReq < _countof(ior); nIOReq++) { // Each I/O request requires a data buffer for transfers chVERIFY(ior[nIOReq].AllocBuffer(BUFFSIZE)); nWritesInProgress++; iocp.PostStatus(CK_WRITE, 0, &ior[nIOReq]); } BOOL bResult = FALSE; // Loop while outstanding I/O requests still exist while ((nReadsInProgress > 0) || (nWritesInProgress > 0)) { // Suspend the thread until an I/O completes ULONG_PTR CompletionKey; DWORD dwNumBytes; CIOReq* pior; bResult = iocp.GetStatus(&CompletionKey, &dwNumBytes, (OVERLAPPED**) &pior, INFINITE); switch (CompletionKey) { case CK_READ: // Read completed, write to destination nReadsInProgress--; bResult = pior->Write(hFileDst); // Write to same offset read from source nWritesInProgress++; break; case CK_WRITE: // Write completed, read from source nWritesInProgress--; if (liNextReadOffset.QuadPart < liFileSizeDst.QuadPart) { // Not EOF, read the next block of data from the source file. bResult = pior->Read(hFileSrc, &liNextReadOffset); nReadsInProgress++; liNextReadOffset.QuadPart += BUFFSIZE; // Advance source offset } break; } } bOk = TRUE; } leave:; } catch (...) { } if (bOk) { // The destination file size is a multiple of the page size. Open the // file WITH buffering to shrink its size to the source file's size. CEnsureCloseFile hFileDst = CreateFile(pszFileDst, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hFileDst.IsValid()) { SetFilePointerEx(hFileDst, liFileSizeSrc, NULL, FILE_BEGIN); SetEndOfFile(hFileDst); } } return(bOk);}int wmain(int argc,wchar_t **argv) {GetDiskFreeSpaceW(NULL,NULL,&BUFFSIZE,NULL,NULL); //cache bytes of per sector for support FILE_FLAG_NO_BUFFERING flag.if(argc < 3)return -1;FileCopy(argv[1],argv[2]);return(0);}//////////////////////////////// End of File //////////////////////////////////
0 0
- I/O 完成端口
- I/O完成端口
- I/O完成端口
- I/O完成端口
- I/O完成端口
- I/O完成端口
- I/O完成端口
- 完成端口(I/O completion):
- 完成端口(I/O completion):
- 完成端口(I/O completion)
- Windows I/O完成端口
- 完成端口(I/O completion)
- Windows I/O完成端口
- 完成端口(I/O completion):
- WinSock : I/O完成端口
- 完成端口I/O模型
- Windows I/O完成端口
- windows I/O完成端口
- 【算法】用lua解决快速排序问题
- u3d特效插件
- 通用网址升级为“.网址”域名意味着什么?
- [UI架构]谈谈UI架构设计的演化
- 为什么越来越的企业亲睐手机号码提取软件,这个软件系统对企业到底有哪些价值?
- I/O完成端口
- 从hdfs中读取文件到hbase
- 随手一记,IOS APP的ICON尺寸
- [笔记]shell使用ps -ef|grep xxx时不显示grep xxx进程的方法
- Hi3516A 音频输入输出的选择, 内部CODEC 还是用外部的I2S CODEC
- 关于调试网页的一些心得
- 关于URL中的国际化参数request_locale
- 奇幻到android studio 的DUANG 蛮捄三
- 4.12、变量的存储类别