2013-08-02 15 views
3

我正在研究Windows上異步套接字I/O的選項。顯然有不止一個選項:我可以使用WSASend ...以重疊結構提供完成回調或事件,或者我可以使用IOCP和(新)線程池。從我通常閱讀,後面的選項是推薦的選項。我應該使用IOCP還是重疊WSASend/Receive?

但是,我不清楚爲什麼我應該使用IOCPs,如果完成例程足夠滿足我的目標:告訴套接字發送這個數據塊並告訴我它是否完成。

我明白,IOCP的東西與CreateThreadpoolIo等組合使用操作系統線程池。但是,「正常」重疊的I/O也必須使用單獨的線程?那麼有什麼區別/劣勢?我的回調是由I/O線程調用並阻止其他內容?

由於提前, 克里斯托夫

回答

2

您可以使用,但對於服務器,IOCP與「完成隊列」會有更好的表現,在一般情況下,因爲它可以使用多個客戶端<>服務器線程,無論是與CreateThreadpoolIo或一些用戶空間線程池。很明顯,在這種情況下,通常是專用的處理程序線程。

重疊的完成 - 例程I/O對客戶更爲有用,恕我直言。完成例程由排隊等待發起I/O請求的線程(WSASend,WSARecv)的異步過程調用觸發。這意味着該線程必須能夠處理APC,並且通常這意味着圍繞某個'blahEx()'調用一段時間(真)的循環。這非常有用,因爲在阻塞隊列或其他線程間信號上等待相當容易,從而允許向線程提供要發送的數據,並且完成例程總是由該線程處理。這個I/O機制使'hEvent'OVL參數免費使用 - 理想的是將通信緩衝區對象指針傳遞到完成例程。

應該避免使用實際的同步事件/信號量/重疊的hEvent參數的重疊I/O。

+0

爲什麼要避免同步事件? – nitzanms

0

Windows IOCP文檔建議每個可用內核每個完成端口不要超過一個線程。超線程使核心數量翻倍。由於使用IOCP會導致出於事實驅動應用程序的所有實際目的,因此使用線程池會給調度程序添加不必要的處理。

如果你仔細考慮它,你就會明白爲什麼:一個事件應該儘可能快地完整服務(或者在初始處理後放置在某個隊列中)。假設五個事件在四核計算機上排隊到IOCP。如果有八個線程與IOCP相關聯,那麼您將面臨調度程序中斷一個事件的風險,即通過使用效率低下的另一個線程開始服務另一個事件。如果中斷的螺紋位於關鍵部分內,也可能很危險。使用四個線程,您可以同時處理四個事件,只要一個事件完成,您就可以從IOCP隊列中最後一個事件開始。

當然,您可能有用於非IOCP相關處理的線程池。

編輯 __ _ __ _ __ _ __ _ __ _ _

套接字(文件句柄工作也沒關係)與IOCP關聯。完成例程在IOCP上等待。一旦請求讀取或寫入套接字完成操作系統 - 通過IOCP - 釋放等待IOCP的完成例程並返回您在調用讀取或寫入時提供的附加信息(我通常將指針傳遞給一個控制塊)。所以完成程序立即「知道」在哪裏找到與完成有關的信息。

如果您傳遞的是涉及控制塊(類似)的信息,那麼該控制塊(可能)需要跟蹤已完成的操作,以便知道下一步該做什麼。 IOCP本身既不知道也不關心。

如果您正在編寫連接到互聯網的服務器,服務器將發出讀取以等待客戶端輸入。該輸入可能會在毫秒或一週後到達,當它輸入時,IOCP將釋放分析輸入的完成例程。通常情況下,它會響應包含輸入中請求的數據的寫入,然後等待IOCP。寫操作完成後,IOCP再次釋放完成程序,該程序發現寫操作已完成,通常會發出新讀操作並開始新的循環。

因此,一個基於IOCP的應用程序通常會消耗非常少(或不)的CPU,直到完成發生時爲止,此時完成例程完全傾斜,直到完成處理,發送新的I/O請求並再次等待在完成端口。除了IOCP超時(可以用來表示內務管理等)之外,所有I/O相關的事情都發生在操作系統中。

爲了使事情進一步複雜化(或簡化),使用WSA例程無需使用套接字,Win32函數ReadFile和WriteFile工作得很好。

+0

這一切都假設你的線程永遠不會阻塞的工作(這將是理想的,但並不總是可行的)。如果線程CAN阻塞,在IOCP上等待額外的線程可以提供幫助;配置文件,看看。理想情況下,每個「連接」(完成鍵)對象都有自己的內部隊列,這樣如果你有自己的線程池可以幫助你確保你的I/O在共享池的其他潛在用戶之前處理爲同一個「連接」獲得多個完成(讀和寫?),你不會使用兩個IOCP線程並讓它們在同一'連接'上作戰...... –

+0

@Olof:所以你仍然會推薦IOCP重疊的I/O,但我應該將一個線程專用於完成端口。我有這個權利嗎?並不限制我應該與端口關聯的句柄數量(使用'ExistingCompletionPort'參數)? – Christoph

+0

IOCP重疊I/O,但它們比等待多個對象(本質上是一種輪詢形式)更有效。在系統中,應該沒有更多的線程等待IOCP,而不是核心(超線程核心數爲2)。所以如果你有四個內核,你不應該有超過四個線程等待IOCP。當然,如果你有兩個IOCP,那麼你不應該有多於四個線程(也許可以像我一樣調整線程優先級)。 –

相關問題