spinlock

轉自:http://www.embedu.org/Column/Column323.htm


作者:李老師,華清遠見嵌入式學院講師。


在初級驅動的我們介紹了幾種同步方式,有同學對自旋鎖有些不理解,現在把這部分內容詳細的講述一下。
自旋鎖與互斥鎖有點類似,只是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保持,調用者就一直循環在那裏看是否該自旋鎖的保持者已經釋放了鎖,"自旋"一詞就是因此而得名。由於自旋鎖使用者一般保持鎖時間非常短,因此選擇自旋而不是睡眠是非常必要的,自旋鎖的效率遠高於互斥鎖。
信號量和讀寫信號量適合於保持時間較長的情況,它們會導致調用者睡眠,因此只能在進程上下文使用(_trylock的變種能夠在中斷上下文使用),而自旋鎖適合於保持時間非常短的情況,它可以在任何上下文使用。如果被保護的共享資源只在進程上下文訪問,使用信號量保護該共享資源非常合適,如果對共巷資源的訪問時間非常短,自旋鎖也可以。但是如果被保護的共享資源需要在中斷上下文訪問(包括底半部即中斷處理句柄和頂半部即軟中斷),就必須使用自旋鎖。
自旋鎖保持期間是搶佔失效的,而信號量和讀寫信號量保持期間是可以被搶佔的。自旋鎖只有在內核可搶佔或SMP的情況下才真正需要,在單CPU且不可搶佔的內核下,自旋鎖的所有操作都是空操作。
跟互斥鎖一樣,一個執行單元要想訪問被自旋鎖保護的共享資源,必須先得到鎖,在訪問完共享資源後,必須釋放鎖。如果在獲取自旋鎖時,沒有任何執行單元保持該鎖,那麼將立即得到鎖;如果在獲取自旋鎖時鎖已經有保持者,那麼獲取鎖操作將自旋在那裏,直到該自旋鎖的保持者釋放了鎖。
無論是互斥鎖,還是自旋鎖,在任何時刻,最多只能有一個保持者,也就說,在任何時刻最多只能有一個執行單元獲得鎖。
自旋鎖的API有(以下翻譯自《LDDv2》英文版):
spin_lock_init(x)
        該宏用於初始化自旋鎖x。自旋鎖在真正使用前必須先初始化。該宏用於動態初始化。
DEFINE_SPINLOCK(x)
        該宏聲明一個自旋鎖x並初始化它。該宏在2.6.11中第一次被定義,在先前的內核中並沒有該宏。
SPIN_LOCK_UNLOCKED
        該宏用於靜態初始化一個自旋鎖。

DEFINE_SPINLOCK(x)等同於spinlock_t x = SPIN_LOCK_UNLOCKED

spin_is_locked(x)

        該宏用於判斷自旋鎖x是否已經被某執行單元保持(即被鎖),如果是,返回真,否則返回假。
spin_unlock_wait(x)
        該宏用於等待自旋鎖x變得沒有被任何執行單元保持,如果沒有任何執行單元保持該自旋鎖,該宏立即返回,否則將循環在那裏,直到該自旋鎖被保持者釋放。
spin_trylock(lock)
        該宏盡力獲得自旋鎖lock,如果能立即獲得鎖,它獲得鎖並返回真,否則不能立即獲得鎖,立即返回假。它不會自旋等待lock被釋放。
spin_lock(lock)
        該宏用於獲得自旋鎖lock,如果能夠立即獲得鎖,它就馬上返回,否則,它將自旋在那裏,直到該自旋鎖的保持者釋放,這時,它獲得鎖並返回。總之,只有它獲得鎖才返回。
spin_lock_irqsave(lock, flags)
         該宏獲得自旋鎖的同時把標誌寄存器的值保存到變量flags中並失效本地中斷。
spin_lock_irq(lock)
         該宏類似於spin_lock_irqsave,只是該宏不保存標誌寄存器的值。
spin_lock_bh(lock)
         該宏在得到自旋鎖的同時失效本地軟中斷。
spin_unlock(lock)
         該宏釋放自旋鎖lock,它與spin_trylock或spin_lock配對使用。如果spin_trylock返回假,表明沒有獲得自旋鎖,因此不必使用spin_unlock釋放。
spin_unlock_irqrestore(lock, flags)
         該宏釋放自旋鎖lock的同時,也恢復標誌寄存器的值爲變量flags保存的值。它與spin_lock_irqsave配對使用。
spin_unlock_irq(lock)
         該宏釋放自旋鎖lock的同時,也使能本地中斷。它與spin_lock_irq配對應用。
spin_unlock_bh(lock)
         該宏釋放自旋鎖lock的同時,也使能本地的軟中斷。它與spin_lock_bh配對使用。
spin_trylock_irqsave(lock, flags)
        該宏如果獲得自旋鎖lock,它也將保存標誌寄存器的值到變量flags中,並且失效本地中斷,如果沒有獲得鎖,它什麼也不做。因此如果能夠立即獲得鎖,它等同於spin_lock_irqsave,如果不能獲得鎖,它等同於spin_trylock。如果該宏獲得自旋鎖lock,那需要使用spin_unlock_irqrestore來釋放。
spin_trylock_irq(lock)
         該宏類似於spin_trylock_irqsave,只是該宏不保存標誌寄存器。如果該宏獲得自旋鎖lock,需要使用spin_unlock_irq來釋放。
spin_trylock_bh(lock)
        該宏如果獲得了自旋鎖,它也將失效本地軟中斷。如果得不到鎖,它什麼也不做。因此,如果得到了鎖,它等同於spin_lock_bh,如果得不到鎖,它等同於spin_trylock。如果該宏得到了自旋鎖,需要使用spin_unlock_bh來釋放。
spin_can_lock(lock)
        該宏用於判斷自旋鎖lock是否能夠被鎖,它實際是spin_is_locked取反。如果lock沒有被鎖,它返回真,否則,返回假。該宏在2.6.11中第一次被定義,在先前的內核中並沒有該宏。
發佈了307 篇原創文章 · 獲贊 52 · 訪問量 98萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章