用完成埠開發大響應規模的Winsock應用程式(3) (轉)

gugu99發表於2008-08-07
用完成埠開發大響應規模的Winsock應用程式(3) (轉)[@more@]

資源的限制條件

在設計任何應用時,其強健性是主要的目標。也就是說,

你的應用程式要能夠應對任何突發的問題,例如併發客戶請求數達到峰值、可用臨時出現不足、以及其它短時間的現象。這就要求程式的設計者注意 NT和2000下的資源限制條件的問題,從容地處理突發性事件。

你可以直接控制的、最基本的資源就是頻寬。通常,使用資料包(UDP)的應用程式都可能會比較注意頻寬方面的限制,以最大限度地減少包的丟失。然而,在使用TCP連線時,伺服器必須十分小心地控制好,防止網路頻寬過載超過一定的時間,否則將需要重發大量的包或造成大量連線中斷。關於頻寬管理的方法應根據不同的應用程式而定,這超出了本文討論的範圍。

虛擬記憶體的使用也必須很小心地管理。透過謹慎地申請和釋放記憶體,或者應用lookas lists(一種快取記憶體)技術來重新使用已分配的記憶體,將有助於控制伺服器應用程式的記憶體開銷(原文為“讓伺服器應用程式留下的腳印小一點”),避免頻繁地將應用程式申請的實體記憶體到虛擬記憶體中(原文為“讓作業系統能夠總是把更多的應用程式地址空間更多地保留在記憶體中”)。你也可以透過SetWorkingSetSize()這個 讓作業系統分配給你的應用程式更多的實體記憶體。

在使用Winsock時還可能碰到另外兩個非直接的資源不足情況。一個是被鎖定的記憶體頁面的極限。如果你把AFD.SYS的緩衝關閉,當應用程式收發資料時,應用程式緩衝區的所有頁面將被鎖定到實體記憶體中。這是因為核心程式需要訪問這些記憶體,在此期間這些頁面不能交換出去。如果作業系統需要給其它應用程式分配一些可分頁的實體記憶體,而又沒有足夠的記憶體時就會發生問題。我們的目標是要防止寫出一個病態的、鎖定所有實體記憶體、讓系統崩潰的程式。也就是說,你的程式鎖定記憶體時,不要超出系統規定的記憶體分頁極限。

在和2000系統上,所有應用程式總共可以鎖定的記憶體大約是實體記憶體的1/8(不過這只是一個大概的估計,不是你計算記憶體的依據)。如果你的應用程式不注意這一點,當你的發出太多的重疊收發,而且I/O沒來得及完成時,就可能偶爾發生ERROR_INSUFFICIENT_RES的錯誤。在這種情況下你要避免過度鎖定記憶體。同時要注意,系統會鎖定包含你的緩衝區所在的整個記憶體頁面,因此緩衝區靠近頁邊界時是有代價的(譯者理解,緩衝區如果正好超過頁面邊界,那怕是1個位元組,超出的這個位元組所在的頁面也會被鎖定)。

另外一個限制是你的程式可能會遇到系統未分頁池資源不足的情況。所謂未分頁池是一塊永遠不被交換出去的記憶體區域,這塊記憶體用來一些供各種核心訪問的資料,其中有的核心元件是不能訪問那些被交換出去的頁面空間的。Windows NT和2000的驅動程式能夠從這個特定的未分頁池分配記憶體。

當應用程式建立一個套接字(或者是類似的開啟某個)時,核心會從未分頁池中分配一定數量的記憶體,而且在繫結、連線套接字時,核心又會從未分頁池中再分配一些記憶體。當你注意觀察這種行為時你將發現,如果你發出某些I/O請求時(例如收發資料),你會從未分頁池裡再分配多一些記憶體(比如要追蹤某個待決的I/O操作,你可能需要給這個操作新增一個自定義結構,如前文所提及的)。最後這就可能會造成一定的問題,作業系統會限制未分頁記憶體的用量。

在Windows NT和2000這兩種作業系統上,給每個連線分配的未分頁記憶體的具體數量是不同的,未來版本的Windows很可能也不同。為了使應用程式的生命期更長,你就不應該計算對未分頁池記憶體的具體需求量。

你的程式必須防止消耗到未分頁池的極限。當系統中未分頁池剩餘空間太小時,某些與你的應用程式毫無關係的核心驅動就會發瘋,甚至造成系統崩潰,特別是當系統中有第三方裝置或驅動程式時,更容易發生這樣的慘劇(而且無法預測)。同時你還要記住,同一臺上還可能執行有其它同樣消耗未分頁池的其它應用程式,因此在設計你的應用程式時,對資源量的預估要特別保守和謹慎。

處理資源不足的問題是十分複雜的,因為發生上述情況時你不會收到特別的錯誤程式碼,通常你只能收到一般性的WSAENOBUFS或者ERROR_INSUFFICIENT_RESOURCES 錯誤。要處理這些錯誤,首先,把你的應用程式工作調整到合理的最大值(譯者注:所謂工作配置,是指應用程式各部分執行中所需的記憶體用量,請參考 .com/msdnmag/issues/1000/slayer/Bugslayer1000."> ,關於記憶體,譯者另有譯文),如果錯誤繼續出現,那麼注意檢查是否是網路頻寬不足的問題。之後,請確認你沒有同時發出太多的收發呼叫。最後,如果還是收到資源不足的錯誤,那就很可能是遇到了未分頁記憶體池不足的問題了。要釋放未分頁記憶體池空間,請關閉應用程式中相當部分的連線,等待系統自行渡過和修正這個瞬時的錯誤。

(譯者) 劉西齊 to:sickid10001@21cn.com">sickid10001@21cn.com


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1008664/,如需轉載,請註明出處,否則將追究法律責任。

相關文章