獲取自旋鎖和禁止中斷的時候為什麼不能睡眠?

似乎網上的說法是因為自旋鎖關閉了搶佔,所以另一個死鎖的進程不會被調度.

而中斷禁止,我則看到這樣的結論:

內核在中斷路徑內不能睡眠,不是技術上做不到,而是沒有理由這麼做,或者說在中斷路徑上睡眠不合理.

感覺太玄學了一點,特來請教.


關中斷和睡眠的邏輯是:

為什麼關中斷的時候不能睡眠?

因為睡眠(普通睡眠,不包括死等)依賴調度器。

為什麼睡眠依賴調度器?

因為調度器通過時鐘中斷判斷何時喚醒任務。

所以,關了中斷,調度器再也無法收到時鐘中斷了,所以就無法喚醒任務了

非要睡眠,只有兩種思路:

第一種是死等(忙等),就是用一個for循環去做等待,缺點是其它任務還是不能調度。

第二種是改造關中斷邏輯,保留時鐘中斷,但這又會產生一個問題:既然要關中斷,那麼勢必是要所有中斷都關,保留一個時鐘中斷算怎麼回事?而且在開發者眼中,關中斷與關調度是等同的概念。

所以操作系統中,關中斷時不能睡眠,睡眠就會睡死了。

spinlock的意思是,關調度,別人別和我搶這個臨界區,同時也不讓其它核搶。

Spinlock(自旋鎖)分為兩種,一種是順帶關中斷的,另一種不是,順帶關中斷的邏輯就不解釋了,跟上面一樣,沒中斷就沒調度。

有的操作系統里,提供不順帶關中斷的spinlock,這種spinlock是危險的,因為會發生死鎖(任務A take了spinlock,發生中斷,中斷裡面又take了spinlock,失敗了,死鎖了),這種情況下理論上是可以產生調度的,但因為這種spinlock關了搶佔,別的任務又不能跑,這個核實際上是浪費了。所以我見到的大部分spinlock,都是順帶關了中斷的。


細節太多了,不多說,細節的話讀ulk或者類似的書,然後照著看點內核代碼就行了

自旋鎖不能睡眠:

A獲得鎖,睡眠,B在等鎖,怎麼辦,可能會等很久哦,B就一直自旋等著,雖然現在循環里用pause命令,但也只能省點電和提高cpu pipeline的性能(hyperthread的情況下),cpu資源還是浪費,光等著不幹活啊

獲得鎖,本來就是要操作一些共享變數,所以要趕緊的,別墨跡,還睡個球子哦

禁止中斷不能睡眠:

禁止中斷就是希望不被打擾,趕緊昨晚自己該做的事,還睡覺,我靠,還想不想幹了

當硬體中斷來的時候,關中斷,這種情況不能睡眠,還有個原因是因為人家進程跑的好好的,你過來打斷人家,還想帶著人家去睡,怎麼可以,中斷上下文不應該睡眠,只有在進程上下文才可以睡眠,技術當然是可以實現,但沒有意義,也不會這樣去設計


自旋鎖本質就是不斷循環直到達到了某種狀態,通常用於中斷服務程序和其他上下文的臨界區訪問中。

禁止中斷就是禁止中斷的意思。

睡眠的意思就是產生調度,也就是說保存好上下文,把cpu切換出去,什麼時候再切換回來,那就是調度器的事情了。然而,關鍵問題來了,調度器是靠什麼驅動的呢,答案就是中斷,包括定時器中斷。

中斷服務程序要求執行是非常快的,否則的話會導致其他中斷無法響應(非嵌套中斷),在可嵌套中斷中會導致調度無法響應。要知道因為中斷是第一原動力,所以在linux內核中,中斷是不允許休眠的,並且提供了所謂的中斷下半部來減輕中斷壓力。好像在某個版本的linux內核中,如果中斷服務程序長時間沒執行完成會直接oops。

在禁止中斷的情況下(理想情況),肯定是不允許調度的,所以也沒有休眠,並且如果你完全禁止了中斷,就不再會有人跟你搶,所以等同於鎖,直到中斷被打開。

以上是針對單核cpu的情況,在多核的情況下,spinlock會和關中斷配合使用。使用不當還會造成死鎖,當然這個和你問的問題也沒有多大關係了。


推薦閱讀:

linux 下root用戶執行rm -rf /後,系統會有哪些反應,會立刻死機嗎?
在Android的發展歷程中有沒有什麼有趣的故事或者小細節?
如何評價NetHack?
Linux 大爆炸:一個內核,無數發行版

TAG:操作系統 | Linux | 計算機科學 | Linux內核 | 自旋鎖編程 |