IOCP
IOCP是唯一一個不需要安全屬性的Windows核心對象。 這是因為IO完成端口在設計時就是隻在一個程序中使用。
原理
通常的辦法是,線程池中的工作線程的數量與CPU核心數量相同,以此來最小化線程切換代價。一個IOCP對象,在作業系統中可關聯着多個Socket和(或)檔案控制端。 IOCP對象内部有一個先進先出(FIFO)隊列,用于存放IOCP所關聯的輸入輸出端的服務請求完成消息。請求輸入輸出服務的程序不接收IO服務完成通知,而是檢查IOCP的消息隊列以确定IO請求的狀态。 (線程池中的)多個線程負責從IOCP消息隊列中取走完成通知并執行資料處理;如果隊列中沒有消息,那麼線程阻塞挂起在該隊列。這些現成進而實作了負載均衡。引自維基百科
IOCP是Windows提供給我們的一整套的東西(工具庫)
1.建立一個隊列(一個完成端口會建立一個)2.裝置操作的隊列包含了裝置
可以有多個裝置對應一個完成端口
對我裝置進行挨個的操作3.線程池多個線程
建立一個完成端口
使用CreateIoCompletionPort原型兩種建立方式:
HANDLE WINAPI CreateIoCompletionPort( _In_ HANDLE FileHandle, // 裝置核心對象 _In_opt_ HANDLE ExistingCompletionPort, // 已存在的完成端口 _In_ ULONG_PTR CompletionKey, // 完成端口的一個Key值,我們可以通過define進行一個設定 _In_ DWORD NumberOfConcurrentThreads // 建立多少個線程,預設值為0, 表示一個核心對應一個線程, 也就是說, 8核心就是8線程, 4核心就是4線程,不建議設定為100個這樣的數量,線程切換會消耗資源 );
如果是8核,實際的實體線程就是8個,可以設定為100個線程,但是它隻是做了一個線程模拟,因為它真正隻能做到8個線程1.先建立一個端口,再打開檔案,再進行端口與裝置的綁定2.建立一個與指定檔案綁定的端口
//建立一個端口 HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); //打開一個檔案 HANDLE hFile = CreateFile(TEXT("Demo.txt"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL); if (hFile != INVALID_HANDLE_VALUE) { // 綁定裝置和端口 CreateIoCompletionPort(hFile, hIOCP, //指定端口 IOCP_KEY_READ, 0); OVERLAPPED oRead = {0}; oRead.Offset = 0; DWORD dwNumberOfBytesTransferred = 100; } else { // GetLastError() }
HANDLE hIOCP = CreateIoCompletionPort( hFile, NULL, IOCP_KEY_READ, 0);
同樣也是要拿到檔案句柄,隻是少了一個建立自由端口的步驟,直接與檔案進行綁定了而已
插入一個請求
PostQueuedCompletionStatus原型
BOOL WINAPI PostQueuedCompletionStatus( _In_ HANDLE CompletionPort, // 完成端口 _In_ DWORD dwNumberOfBytesTransferred, // 傳輸的資料長度, 用于GetQueuedCompletionStatus擷取的時候 _In_ ULONG_PTR dwCompletionKey, // IO完成端口的KEY _In_opt_ LPOVERLAPPED lpOverlapped // OVERLAPPED結構體指針 );
從指定的IO完成端口取資料
GetQueuedCompletionStatus原型:注意:
BOOL WINAPI GetQueuedCompletionStatus( _In_ HANDLE CompletionPort, // IO完成端口 _Out_ LPDWORD lpNumberOfBytes, // 取出的資料數的指針 _Out_ PULONG_PTR lpCompletionKey, // IO完成端口的KEY _Out_ LPOVERLAPPED *lpOverlapped, // 指向OVERLAPPED結構體指針的指針 _In_ DWORD dwMilliseconds // 等待的毫秒數 );
如果沒有完成資料包隊列, 該功能将等待與完成端口關聯的待處理的IO操作完成.
如果在指定時間内沒有出現完成資料包, 則函數逾時, 傳回FALSE, 并将 *lpOverlapped 設定為NULL
如果dwMilliseconds是INFINITE, 則該函數永遠不會逾時
如果dwMilliseconds為零, 并且沒有IO操作出現, 則該函數将立即逾時.