本文參考了用戶態非搶占式線程庫實現 一文以及GNU Pth 。前者是一種用戶態線程庫的簡單實現,屬于一個很好的demo,后者就是大家熟知的Pthread的用戶態實現,比較完善。
Keywords: User-Space MultiThreading, Pth
所謂多線程,簡單講就是能夠讓幾個不同的代碼片段輪流執行。內核實現多線程的方法比較直觀,在每次時鐘中斷到來時或者用戶調用syscall陷入內核時進行上下文切換即可。用戶態切換線程要解決兩個問題:
1、時機,即何時切換線程?
2、方法,即怎樣切換上下文?
為了決定切換時機,需要確定所設計的線程庫是可剝奪(preemptive)的還是不可剝奪(non-preemptive)的。一般,用戶態線程庫都選擇使用不可剝奪的設計方案,這么做的好處是將控制權交給用戶,而用戶最了解何時需要放棄執行權。這么做減少了系統切換次數,實現了最高的CPU利用率,非常適合用于科學計算環境。但是,另一方面這么做也存在缺點:其它線程的響應速度變慢,他們必須等到當前CPU放棄執行權后才能被執行。能不能將用戶線程設計成可剝奪的呢?這應該也是可行的。每個用戶線程運行一段時間后會被迫暫停執行,被動地將控制權交回給調度器。怎樣才能“被迫暫停執行”?這是方法問題,下面就要講到。
對于不可剝奪方式,需要用戶編寫程序的時候主動調用諸如thread_yeild(), thread_wai()之類的函數,這些函數會將當前用戶線程的執行上下文保存起來,然后讓調度器選擇一個新的用戶線程投入執行。底層操作系統提供了一些列的機制支持上下文的獲得和切換,如setjmp,longjmp,getcontext,swapcontext等。用戶態非搶占式線程庫實現 一文使用了前面兩個函數,GNU Pth 使用了后面兩個函數。可剝奪方式的實現需要更多的操作系統支持,如可以利用alarm函數周期性地產生用戶態中斷,每次中斷到來的時候線程庫進行線程切換。
單純的用戶態線程庫一般都是基于一個單線程進程實現的,一旦用戶線程阻塞,這個進程就被阻塞,進而導致整個用戶態線程組得不到CPU。基于單進程實現的用戶態線程庫在SMP/多CPU環境下性能很差,多出來的核無法被線程庫利用,這跟當前的微處理器架構發展趨勢十分不符。為了解決這個問題,可以考慮使用一種混合結構:在少量內核線程的基礎上實現大量的用戶線程。
最后思考一個問題:為什么用戶態線程庫比內核態線程庫具有更高的性能呢?其實用戶態線程庫同樣離不開進入內核態這一過程,以getcontext,swapcontex實現方式為例,getcontext要進出一次內核,swapcontex又要進出一次內核,而內核線程切換則只需要一次時鐘中斷,只進出內核一次即可。這么說來,用戶態線程庫的性能應該劣于內核態線程庫。但是,注意到每次時鐘中斷所做的工作遠遠不止上下文切換這么簡單,這應該是用戶態線程庫更優的原因吧。基于這個分析,如果應用需要創建的線程數并不多,二者應該性能相當。但是,一旦線程數巨大且切換頻繁,用戶態線程庫的優勢就能體現出來了。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/maray/archive/2009/12/05/4946245.aspx
posted on 2010-05-30 14:33
何克勤 閱讀(1396)
評論(0) 編輯 收藏 所屬分類:
Linux 多線程