正确使用自旋锁、互斥锁
最近在看alios-things的代碼發現驅動程序中大量使用了自旋鎖 。
如tty.c里面的函數實現都是通過自旋鎖來實現對資源的訪問保護。
看到這里首先會有疑問,自旋鎖能保護臨界區嗎?
一般來說,自旋鎖是用于多核系統的不同核心之間對同一個數據區的競爭訪問,對于同一個核上的不同線程是不具備防護功能的。(網上有文章解析自旋鎖是讓線程原地等待,并沒有突出smp環境下的核間競爭,這是不對的,自旋鎖就是永遠多核處理器之間的資源防護,而不是多線程的資源防護)
懷著上述疑問,打開aos_spinlock.c看一下相關接口底層實現,發現這些spinlock操作實際上是復合了關中斷的操作的。
所以,看到這里,這些接口應該命名為aos_irqlock_xxx更為合適。不然在單核情況下,這里的自旋鎖就僅保存了鎖中斷功能,名字和功能就對不上了。
另外,繼續深入的想一想,驅動中大量使用關中斷是否合適呢?
在大量io存在的情況下,這種關中斷可能要降低系統性能,這時候互斥鎖應該是更好的選擇。
互斥鎖在lock、unlock時會有短暫的關中斷,在鎖持有過程中是不需要關閉中斷的。這樣也就可以在大量io的過程給中斷以及其他線程運行的機會,可以在io過程更充分的利用處理器資源。
網上也有討論不關中斷,獨立使用自旋鎖的,如果確信自己在干什么,當然也沒問題,如果是設計一套通用的接口提供給其他用戶使用,并不能確定用戶的使用場景,還是老老實實關中斷使用吧。
上網搜了一下自旋鎖,發現不少錯誤描述,很多將自旋鎖和互斥鎖做對比的,解析的也比較雷同,都是一些在閱讀代碼過程中產生的一些感性認識,缺乏理論依據。
下面是我對自旋鎖的總結,如果有疑問或者不對的地方請留言指正,感謝!
首先,自旋鎖是為解決多核系統的資源競爭而設計的,需要處理器的原子操作來實現。其次,自旋鎖是其他內核保護機制的底層基礎,如信號量、互斥鎖等在多核系統里是要依賴自旋鎖來實現其功能。
單核情況下,只要關閉中斷,系統就相當是獨占的,但是在多核情況下,關閉中斷,只能保證當前處理器不被搶奪,而不能保證其他處理器核上的線程來競爭資源 。
多核情況下,處理器提供了特殊指令實現對單元數據的原子訪問,可以允許每個核心來對該單元數據的狀態進行原子的設置操作,如果有多核同時進行這一設置操作,則只有一個會成功,其他的返回失敗,失敗的可以重復這一過程,直到成功,這就是自旋鎖的實現原理。
根據上述描述可知,自旋鎖的持有時間要盡可能的短,否則,可能導致其他處理器被長時間自旋掛起。傳統的互斥量、信號量等內核元素就是獲得自旋鎖后快速對自身變量完成設置后歸還自旋鎖(設置自旋鎖為空閑狀態)。
總結
以上是生活随笔為你收集整理的正确使用自旋锁、互斥锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++学习45 流成员函数put输出单
- 下一篇: 重学JavaWeb —— JSP,简单全