2010-07-30 52 views
4

我讀到的系統上有1個CPU和非預先Linux內核(2.6.x),spin_lock調用相當於一個空調用,因此以這種方式實現。非預先Linux內核上的spin_lock

我無法理解:它不應該等同於互斥體上的睡眠嗎?即使在非預編譯的內核中,中斷處理程序仍然可能會被執行,或者我可能會調用一個函數來使原始線程進入休眠狀態。所以,如果一個空的spin_lock調用是作爲互斥體實現的,那麼它就是「安全」的,這是不正確的。

有什麼我不明白嗎?

回答

5

«Linux設備驅動程序»,由喬納森·科比特,亞歷山德羅Rubini和葛雷格·克羅哈曼報價:

如果一個非搶佔的單處理器系統曾經走進一個 鎖旋轉,它會旋轉永遠;沒有其他線程能夠獲得CPU釋放鎖(因爲它不能屈服)。 正因爲如此,在未啓用 搶佔單處理器系統上自旋鎖操作進行了優化,什麼也不做,用的 不同之處在於改變IRQ屏蔽狀態的那些(在Linux中,這將是 spin_lock_irqsave())。由於搶佔,即使您從未使用 希望您的代碼在SMP系統上運行,您仍需要實施 正確的鎖定。

如果您對可以在中斷環境(硬件或軟件)中運行的代碼執行的自旋鎖感興趣,則必須使用禁用中斷的形式spin_lock_*。如果不這樣做,只要進入臨界區時中斷到達,就會使系統死鎖。

+0

事實上,由於spin_lock調用禁用搶佔,所以先發制人的單處理器系統的情況是相同的。 – Dipstick 2011-07-02 08:11:28

+0

-1複製/粘貼沒有署名。在引用時,請說清楚並至少提供原作者的姓名! http://books.google.ch/books?id=M7RHMACEkg4C&pg=PT137&lpg=PT137&dq=%22If+a+nonpreemptive+uniprocessor+system+ever+went+into+a+spin+on+a+lock%22&source=bl&ots = s1I5OjeNVv&SIG = VklYdozQ9pAkuzxUAdvlPjcFHe8&HL = EN&SA = X&EI = s_7tUJ_UJ6qN4gS68oHACg&VED = 0CFoQ6AEwBw – Macmade 2013-01-09 23:38:01

1

根據定義,如果您使用的是非搶先式內核,則不會被搶佔。如果你做自己的多任務處理,那不是內核的問題;那是你的問題。中斷處理程序可能仍會執行,但它們不會導致上下文切換。

+1

此外,這是否意味着我不能在我的螺旋鎖臨界區進行可能阻塞的調用? (如kmalloc或printk?) – Emiliano 2010-07-30 14:56:32

+0

除非所有其他用戶在自鎖之前禁用IRQ(請參見Erics答案),否則不應使用自旋鎖。如果允許的話,您描述的情況會導致死鎖(處理器在IRQ處理程序中旋轉,但如果沒有處理器運行其他代碼,鎖定永遠不會釋放)。 – 2010-07-30 18:59:23

+0

@happy_emi要回答你的另一個問題,在拿着螺旋鎖的同時,你不應該打電話,可能會阻止,睡眠或重新安排,因爲這也可能導致死鎖。 – 2010-07-30 21:54:22

6

如果您在非搶先式內核上使用spin_lock()來屏蔽數據與中斷處理程序之間的關係,則會導致死鎖(在單處理器計算機上)。

如果中斷處理程序在其他內核代碼持有鎖的同時運行,它將永遠旋轉,因爲常規內核代碼無法恢復並釋放鎖。

只有鎖定座始終能夠完成時才能使用自旋鎖。

中斷處理程序可能需要的鎖的解決方案是使用spin_lock_irqsave(),該鎖在禁用自旋鎖時禁用中斷。有了1個CPU,沒有中斷處理程序可以運行,所以不會出現死鎖。在smp上,一箇中斷處理程序可能開始在另一個cpu上旋轉,但由於持有該鎖的cpu不能被中斷,因此該鎖最終將被釋放。

6

要回答你的問題的兩個部分:

即使在非preemtive內核中斷處理程序可能仍然例如執行...

spin_lock()是不應該防範中斷處理程序 - 只有用戶上下文內核代碼。 spin_lock_irqsave()是中斷禁用版本,並且此不是在非搶先式單處理器上無操作。

......或者我可能會調用一個函數來讓原始線程進入睡眠狀態。

在持有自旋鎖時不允許睡覺。這是「Scheduling while atomic」錯誤。如果你想睡覺,你必須使用互斥鎖(再次 - 這些不是非搶先式單處理器上的禁止操作)。