天天看點

自旋鎖-信号量-互斥體

linux核心中自旋鎖使用注意事項:

(1).自旋鎖實際上是忙等鎖,當鎖不可用時,CPU一直循環執行“測試并裝置”該鎖直到可用而取得該鎖,CPU在等待自旋鎖時不做任何有用的工作,僅僅是等待。是以隻有在占用鎖的時間極短的情況下,使用自旋鎖才是合理的。當臨界區很大,或有共享裝置時候,需要較長時間占用鎖的時候,使用自旋鎖會降低系統的性能。

(2)自旋鎖可能導緻系統死鎖。引發這個問題最常見的情況是遞歸使用一個自旋鎖,即一個已經擁有了某個自旋鎖的CPU想第二次獲得這個自旋鎖,則該CPU将死鎖。

(3)自旋鎖鎖定期間不能調用可能引起程序排程的函數。如果程序獲得自旋鎖後再阻塞,如調用copy_from_user(),copy_to_user(),kmalloc(),和msleep等函數,則可能導緻核心的崩潰。

(4)在單核情況下程式設計的時候, 也應該認為自己的CPU是多核的,驅動特别強調跨平台。例如,在單CPU情況下,若中斷和程序可通路同一臨界區,程序裡調用spin_lock_irqsave()是安全的,在中斷裡其實不調用spin_lock()也是沒有問題的。因為spin_lockl_irqsave()可以保證這個CPU的中斷服務程式不可能執行。但是如果CPU變成多核,spin_lockl_irqsave()不能屏蔽另一外一個核的中斷,多以另外一個核就可能造成并發問題。是以無論如何,我們在中斷代碼服務程式裡也應該調用spin_lock()。

Linux中使用信号量注意事項:

(1).信号量不能使用在中斷上下文中,因為擷取信号量時,會導緻休眠。

與自旋鎖不同的是,當程序擷取不到信号量時,程序不會原地打轉而是進入休眠狀态。 

Linux中使用互斥體注意事項:

(1).互斥體是程序級的,用于多個程序之間對資源的互斥,雖然也是在核心中,但是該核心執行路徑是以程序的身份,代表程序來争奪資源的。如果競争失敗,會發生程序上下文切換,目前程序進入睡眠,CPU将運作其他程序,鑒于程序上下文切換開銷也很大,是以隻有當程序占用CPU資源時間較長時,用互斥體才是比較好的選擇。

當所要保護的臨界區通路時間比較短時,用自旋鎖非常友善,因為他可以節省上下文切換的時間,但是CPU得不到自旋鎖會在那裡空轉,直到其他執行單元,解鎖為止,是以要求鎖不能在臨界區長時間停留,否則會降低系統的效率。

總結:1.當鎖不能被擷取到時,使用互斥體的開銷是程序上下文切換時間,使用自旋鎖的開銷是等待獲得自旋鎖(由臨界區執行時間決定)。若臨界區較小,宜使用自旋鎖,若臨界區較大,應該使用互斥體。

     2.互斥體所保護的臨界區可能包含可能引起阻塞的代碼,而自旋鎖則絕對要避免用來保護包含這樣代碼的臨界區,因為阻塞意味着要進行程序的切換,如果程序被切換出去後,另一個程序企圖擷取本自旋鎖,死鎖就會發生。

3.互斥體存在于程序上下文,是以如果被保護的共享資源需要在中斷或軟中斷情況下使用,則在互斥體和自旋鎖之間隻能選擇自旋鎖,如果一定要使用互斥體,則隻能通過mutex_trylock()方式進行,不能擷取就立即傳回以避免阻塞。

繼續閱讀