完成端口在MSDN中的專題翻譯


I/O completion ports provide an efficient threading model for processing multiple asynchronous I/O requests on a multiprocessor system. When a process creates an I/O completion port, the system creates an associated queue object for requests whose sole purpose is to service these requests.Processes that handle many concurrent asynchronous I/O requests can do so more quickly and efficiently by using I/O completion ports in conjunction with a pre-allocated thread pool than by creating threads at the time they receive an I/O request.
IO完成端口在多處理器系統上提供一個高效的線程模型來處理併發異步IO請求。當一個進程創建一個IO完成端口後,系統會創建一個與之關聯的隊列對象來專門爲這些請求服務。進程在預先分配的線程池的幫助下,會快速高效的處理併發的異步請求,這比來一個請求再去創建一個線程好多了。

How I/O Completion Ports Work 完成端口怎麼工作
The CreateIoCompletionPort function Creates an IO completion port and associates one or more file handles with that port.When an asynchronous IO operation on one of these file handles completes, an IO completion packet is queued in first-in-first out(FIFO) order to the associated IO completion port.One powerful use for this mechanism is to combine the synchronization point for multiple file handles into a single object, although there are also other useful applications.
CreateIoCompletionPort函數創建一個完成端口並將多個文件句柄與之關聯。當某個句柄上的一個異步IO操作完成,一個IO完成包以先進先出的順序放到關聯的完成端口裏。這樣的一個明顯的好處是將多個文件句柄的異步操作合併到一個對象上,當然還有一些其它有用的好處。

Note
The term file handle as used here refers to system abstraction representing an overlapped IO endpoint, not only a file on disk.For example, it can be a network endpoint, TCP socket, named pipe, or mail slot.Any system object that supports overlapped IO can be used.For a list of related IO functions, see the end of this topic.
注意
這裏的文件句柄表示的是代表重疊IO類型的一個抽象,並不僅僅是磁盤上的文件。例如,還可以是網絡端點,TCP socket,命名管道,或者郵槽。任何支持重疊IO的系統對象都可以用。相關的IO函數,可以參看這個主題的尾部。


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 IO completion port, rather than waiting directly for the asynchronous IO to complete.Threads that block their execution on an IO completion port are released in last-in-first-out(LIFO) order, and the next completion packet is pulled from the IO 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 IO completion.
一個線程(被主線程創建的或主線程本身)使用GetQueuedCompletionStatus函數等待一個完成包插入到完成端口裏,而不是直接等待異步IO的完成。被完成端口阻塞的線程採取後進先出的順序釋放,下一個完成包被從完成端口的FIFO隊列中提取出來給剛釋放的線程。這也就是說,當一個完成包被解壓給一個線程時,系統釋放最近與完成端口關聯的線程,給它傳遞等待最久的完成包。

Although any number of threads can call GetQueuedCompletionStatus for a specified IO completion port, when a specified thread calls GetQueuedCompletionStatus the first time, it becomes associated with the specified IO completion port until one of three things occurs: The thread exits, specifies a different IO completion port, or closes the IO completion port.In other words, a single thread can be associated with, at most, one IO completion port.
儘管任意線程可以調用GetQueuedCompletionStatus來查詢一個特定的IO完成端口,但一個特定的線程第一次調用GetQueuedCompletionStatus時,這個線程就會與特定的完成端口關聯直到下面三件事之一發生:線程退出,標識一個不同的IO完成端口,或者關閉IO完成端口,換句話說,一個單一的線程只能也最多與一個IO完成端口關聯。

When a completion packet is queued to an IO completion port, the system first checks how many threads associated with that port are running.If the number of threads running is less than the concurrency value(discussed in the next section), one of the waiting threads(the most recent one) is allowed to process the completion packet.When a running thread completes its processing, it typically calls GetQueuedCompletionStatus again, at which point it either returns with the next completion packet or waits if the queue is empty.
當一個完成包被插入到完成端口裏,系統首先檢查多少個與這個完成端口關聯的線程正在運行。如果運行線程的數量小於併發值(在下節討論), 一個等待的線程(最晚被置爲等待狀態)被允許去處理完成包。當一個運行的線程完成它的處理時,它照例再一次調用GetQueuedCompletionStatus,此時線程或者得到下一個完成包或者一直等待如果隊列是空的話。

Threads can use the PostQueuedCompletionStaus function to place completion packets in an IO completion port's queue. By doing so, the completion port can be used to receive communications from other threads of the process, in addition to receiving IO completion packets from the IO system.The PostQueuedCompletionStatus function allows an application to queue its own special-purpose completion packets to the IO completion port without starting an asynchronous IO operation.This is useful for notifying worker threads of external events, for example.
線程可以用PostQueuedCompletionStatus函數來放置完成包到一個IO完成端口的隊列中。通過這樣做,除了可以從IO系統中接收IO完成包外,完成端口還可以被用於接收進程中其它線程的消息。PostQueuedCompletionStatus函數允許一個程序來投遞它自己的有特別用途的完成包到IO系統而不需要啓動一個異步IO操作。這樣很有用,例如,可以用於通知工作線程額外的事件。

The IO completion port handle and every file handle associated with that particular IO completion port are known as references to the IO completion port.The IO completion port is released when there are no more references to it.Therefore, all of these handles must be properly closed to release the IO completion port and its associated system resources.After these conditions are satisfied, an application should close the I/O completion port handle by calling the CloseHandle function.(這段不用翻譯了,就是關閉句柄,前篇翻譯過了。)

Threads and Concurrency
The most important property of an IO completion port to consider carefully is the concurrency value.The concurrency value of a completion port is specified when it is created with CreateIoCompletionPort via the NumberOfConcurrentThreads parameter.This value limits the number of runnable threads associated with the completion port.When the total number of runnable threads associated with the completion port reaches the concurrency value, the system blocks the execution of any subsequent threads associated with that completion port until the number of runnable threads drops below the concurrency value.
線程和併發
仔細斟酌,會發現併發值是完成端口最重要的屬性。完成端口的併發值在調用CreateIoCompletionPort時通過參數NumberOfConcurrentThreads這個參數傳遞進來。這個值限制與完成端口關聯的可運行線程數量。當與完成端口關聯的可運行線程數量達到併發值時,系統阻塞所有與完成端口關聯的後續線程的執行,直到可運行線程的數量降到併發值以下。


The most efficient scenario occurs when there are completion packets waiting in the queue, but no waits can be satisfied because the port has reached its concurrency limit.Consider what happens with a concurrency value of on an multiple threads waiting in the GetQueuedCompletionStatus function calls.In this case, if the queue always has completion packets waiting, when the running thread calls GetQueuedCompletionStatus, it will not block execution because, as mentioned earlier, the thread queue is LIFO.Instead, this thread will immediately pick up the next queued completion packet.No thread context switches will occur, because the running thread is continually picking up completion packets and the other threads are unable to run.
最高效的場景是:有完成包在隊列裏等待,但是沒有一個等待可以被處理,因爲完成端口已經達到了併發限制。考慮下面情況會發生什麼:很多線程在併發值限制的情況下等待在GetQueuedCompletionStatus的調用處。在這種情況下,如果隊列中總是有完成包在等待處理,當運行的線程調用GetQueuedCompletionStatus,這個線程將不會阻塞,因爲就像前面說的,線程隊列是後進先出。相反,這個線程會立即拿到下一個隊列中的完成包。不會發生線程切換,因爲運行的線程在連續不斷的處理完成包而其他線程不能運行。

Note
In the previous example, the extra threads appear to be useless and never run, but that assumes that the running thread never gets put in a wait state by some other mechanism, terminates, or otherwise closes its associated IO completion port.Consider all such thread execution ramifications when desining the application.
注意
在前面的例子中,額外的線程看起來沒什麼用,一直不能運行,但這樣的前提是運行的線程永遠不會等待,終止,或者用別的方法關閉與其關聯的完成端口。當設計程序時,要考慮所有這些線程執行情況。


The best overall maximum value to pick for the concurrency value is the number of CPUs on the computer.If your transaction required a lengthy computation, a larger concurrency value will allow more threads to run.Each completion packet may take longer to finish, but more completion packets will be processed at the same time.You can experiment with the concurrency value in conjunction with profiling tools to achieve the best effect for your application.
大體上說,最合適的併發值是計算機的CPU數量。如果你的事務需要很長的計算時間,一個大的併發值可以允許更多的線程運行。每個完成包可能花很多時間來處理,但是多個完成包可以同時被處理。你可以用不同的分析工具測試不同的併發值來爲你的應用程序挑選最合適的值。
發佈了132 篇原創文章 · 獲贊 10 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章