表示還是自己看MSDN最直接,別人的介紹都是嚼剩下,有木有? IO完成端口為在多處理器系統處理多個異步IO請求提供一個高效的線程模型。當一個進程新建一個完成端口,操作系統新建一個目的為服務這些請求的隊列對象。通過利用IO完成端口與相關聯的預先分配的線程池而不是新建線程來處理當前請求,處理多個並發的異步IO請求會更快更有效。 IO完成端口如何工作 函數CreateIoCompletionPort創建一個IO完成端口,並在這個端口上關聯一個或多個file【文件描述符】。當在這些操作符上的一個或者多個的一個異步IO操作完成時,一個IO完成包(packet)就進入與IO完成端口關聯的先進先出隊列。這個機制的一個強大的用法是在單個對象裡進行多個描述符間的同步,盡管他們還有其他有用的應用。請注意:在隊列中的數據包可能會以不同的順序出列。【這句不怎麼理解,是不是多個線程在出列操作?】 注意: 屬於file handle是代表重疊IO端點的一種系統抽象代表,而不只是磁盤上的file。例如,可以是網絡端點,TCP socket,命名管道或者mail slot。任何支持完成端口的系統對象都可以被利用。 When a file handle is associated with a completion port, the status block passed in will not be updated until the packet is removed from the completion port. The only exception is if the original operation returns synchronously with an error. A thread (either one created by the main thread or the main thread itself) uses the GetQueuedCompletionStatus function to wait for a completion packet to be queued to the I/O completion port, rather than waiting directly for the asynchronous I/O to complete. Threads that block their execution on an I/O completion port are released in last-in-first-out (LIFO) order, and the next completion packet is pulled from the I/O completion port's FIFO queue for that thread. This means that, when a completion packet is released to a thread, the system releases the last (most recent) thread associated with that port, passing it the completion information for the oldest I/O completion. 當描述符與一個完成端口相關聯,傳進來的狀態快不會被更新直到包從完成端口上拿走。唯一的異常是原來的操作異步返回錯誤。一個線程(可以是主線程創建的或者主線程自己)用GetQueuedCompletionStatus 函數來等待進入完成端口的包,而不是直接等待異步IO完成。在完成端口阻塞操作的線程會以後進顯出釋放,而這個線程的下一個端口包會以先進先出隊列從IO端口取出。這就意味著,當一個包喂給了一個線程,系統將釋放最後一個與端口關聯的線程,同時為最老的完成端口傳遞完成端口信息【這句沒怎麼看懂】。 盡管任何線程都能向特定的完成端口調用GetQueuedCompletionStatus,當一個具體的線程第一次調用它時,它開始與特定的完成端口關聯知道以下三種情況中的一種發生: 1.線程存在,關聯了另外一個完成端口; 2.關閉了完成端口。 也就是說一個線程只能關聯一個完成端口。 當一個完成包被放入完成端口的隊列中,系統首先檢查當前有多少與端口關聯的線程。如果運行中的線程數目小於並發值,最近的一個等待線程被允許處理完成包。當一個運行線程完成處理,它將要繼續再次調用GetQueuedCompletionStatus,因為在這個點它要麼等待下一個完成包,要麼等待到包隊列為空。 線程可以調用PostQueuedCompletionStatus來投遞完成包到IO端口的隊列。通過這樣做,完成端口可以用來收取其他線程或者進程的交互數據,還可以從IO系統收取完成端口包。PostQueuedCompletionStatus函數允許應用程序不開啟異步IO操作,就能向IO完成端口投遞特定的完成包。比如,這對於以外不事件通知工作線程是有用的。 IO完成端口句柄和每個描述符句柄與特定IO完成端口關聯被認為提領了完成端口,當沒有與它關聯的引用時完成端口被釋放。因此,所有這些句柄必須被適合地關心以釋放完成端口和它關聯的系統資源。這些條件滿足後,通過調用CloseHandle來關閉完成端口句柄。 注意 一個完成端口與創建它的進行關聯,不能被進程間共享。然而,單個句柄可以在同一進程的不同線程中共享。 線程和並發 IO完成端口的最重要的性質是並發值。完成端口的並發值在通過CreateIoCompletionPort的theNumberOfConcurrentThreads參數被確定。這個值限制了與完成端口相關聯的線程的數目。當關聯線程數目超過了這個並發值,系統將會阻塞任何之後的線程,直到運行線程數目降到並發值。 最有效的語義是當有完成包在隊列裡,但沒有等待會被滿足因為端口已經達到並發限制。考慮到在並發值下,用一個或多個線程等待在GetQueuedCompletionStatus調用。在這種情況下,如果隊列有完成包在等待,當運行線程調用GetQueuedCompletionStatus,他將不會阻塞,因為如上面提到的線程隊列是先進先出的。取而代之的是,這個線程將立即拿到下一個完成包。沒有上下文切換發生,因為運行線程連續地拿完成包,另外的線程不能運行【這段都怎麼理解】。 注意 在前面的例子裡,額外的線程好像是無用的,並且不會允許,但假設運行線程因為某些同步機制從未進入等待狀態,停止或者關閉它關聯的完成端口。注意當重新設計應用的時候所有這些線程的執行分支。 最好的並發最大值是電腦的CPU個數。如果你的傳輸要求一個復雜的計算,這就需要大點的並發值。每個完成包可能完成的時間增加,但更多的完成包被並發地處理。你可以試驗設置並發值來達到程序的最優化。 系統運行當一關聯同一完成端口的線程因為一些原因(例如SuspendThread函數)在等待狀態時,另一線程等待在GetQueuedCompletionStatus來處理完成包。當這個在等待狀態的線程開始運行,當活躍線程數目超過並發值這將是一個短暫的過程。然而,系統將通過不允許任何啟動新的活躍線程迅速減少活躍線程數目,直到活躍線程數目下降到並發值。這也是你可以在線程池裡創建比並發值多的線程的原因。線程池管理超越了本話題的范圍,但是一個好的經驗是在線程池裡最少擁有系統處理器兩倍的線程數(>=2*corenum)。可以參考 Thread Pools。 支持的IO函數 下列的函數可以被用來通過利用完成端口來啟動IO操作。你必須傳遞OVERLAPPED結構的一個實例和之前與IO關聯的描述符給這些函數(通過調用CreateIoCompletionPort)來開啟IO完成端口機制: ConnectNamedPipe DeviceIoControl LockFileEx ReadDirectoryChangesW ReadFile TransactNamedPipe WaitCommEvent WriteFile WSASendMsg WSASendTo WSASend WSARecvFrom WSARecvMsg WSARecv ok,翻譯完了,很多句子不通順啊,有的地方自己都不明白啊!