自旋锁spinlock解析
1 基礎概念
自旋鎖與相互排斥鎖有點類似,僅僅是自旋鎖不會引起調用者睡眠。假設自旋鎖已經被別的運行單元保持。調用者就一直循環在那里看是否該自旋鎖的保持者已經釋放了鎖。"自旋"一詞就是因此而得名。
因為自旋鎖使用者一般保持鎖時間很短,因此選擇自旋而不是睡眠是很必要的,自旋鎖的效率遠高于相互排斥鎖。
信號量和讀寫信號量適合于保持時間較長的情況,它們會導致調用者睡眠,因此僅僅能在進程上下文使用(_trylock的變種可以在中斷上下文使用)。而自旋鎖適合于保持時間很短的情況,它可以在不論什么上下文使用。
假設被保護的共享資源僅僅在進程上下文訪問,使用信號量保護該共享資源很合適,假設對共巷資源的訪問時間很短,自旋鎖也能夠。可是假設被保護的共享資源須要在中斷上下文訪問(包含底半部即中斷處理句柄和頂半部即軟中斷)。就必須使用自旋鎖。
自旋鎖保持期間是搶占失效的,而信號量和讀寫信號量保持期間是能夠被搶占的。
自旋鎖僅僅有在內核可搶占或SMP的情況下才真正須要。在單CPU且不可搶占的內核下,自旋鎖的全部操作都是空操作。
跟相互排斥鎖一樣,一個運行單元要想訪問被自旋鎖保護的共享資源,必須先得到鎖,在訪問完共享資源后。必須釋放鎖。假設在獲取自旋鎖時,沒有不論什么運行單元保持該鎖,那么將馬上得到鎖;假設在獲取自旋鎖時鎖已經有保持者,那么獲取鎖操作將自旋在那里,直到該自旋鎖的保持者釋放了鎖。
2 自旋鎖的API
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中第一次被定義,在先前的內核中并沒有該宏。
3 API 使用場景
假設被保護的共享資源僅僅在進程上下文訪問和軟中斷上下文訪問,那么當在進程上下文訪問共享資源時。可能被軟中斷打斷,從而可能進入軟中斷上下文來對被保護的共享資源訪問,因此對于這樣的情況。對共享資源的訪問必須使用spin_lock_bh和spin_unlock_bh來保護。
當然使用spin_lock_irq和spin_unlock_irq以及spin_lock_irqsave和spin_unlock_irqrestore也能夠。它們失效了本地硬中斷,失效硬中斷隱式地也失效了軟中斷。
可是使用spin_lock_bh和spin_unlock_bh是最恰當的,它比其它兩個快。
假設被保護的共享資源僅僅在進程上下文和tasklet或timer上下文訪問,那么應該使用與上面情況同樣的獲得和釋放鎖的宏,由于tasklet和timer是用軟中斷實現的。
假設被保護的共享資源僅僅在一個tasklet或timer上下文訪問。那么不須要不論什么自旋鎖保護,由于同一個tasklet或timer僅僅能在一個CPU上執行。即使是在SMP環境下也是如此。
實際上tasklet在調用tasklet_schedule標記其須要被調度時已經把該tasklet綁定到當前CPU。因此同一個tasklet決不可能同一時候在其它CPU上執行。
timer也是在其被使用add_timer加入到timer隊列中時已經被幫定到當前CPU。所以同一個timer絕不可能執行在其它CPU上。當然同一個tasklet有兩個實例同一時候執行在同一個CPU就更不可能了。
假設被保護的共享資源僅僅在兩個或多個tasklet或timer上下文訪問。那么對共享資源的訪問僅須要用spin_lock和spin_unlock來保護,不必使用_bh版本號,由于當tasklet或timer執行時,不可能有其它tasklet或timer在當前CPU上執行。
假設被保護的共享資源僅僅在一個軟中斷(tasklet和timer除外)上下文訪問,那么這個共享資源須要用spin_lock和spin_unlock來保護,由于相同的軟中斷能夠同一時候在不同的CPU上執行。
假設被保護的共享資源在兩個或多個軟中斷上下文訪問,那么這個共享資源當然更須要用spin_lock和spin_unlock來保護。不同的軟中斷可以同一時候在不同的CPU上執行。
假設被保護的共享資源在軟中斷(包含tasklet和timer)或進程上下文和硬中斷上下文訪問。那么在軟中斷或進程上下文訪問期間,可能被硬中斷打斷,從而進入硬中斷上下文對共享資源進行訪問,因此。在進程或軟中斷上下文須要使用spin_lock_irq和spin_unlock_irq來保護對共享資源的訪問。
而在中斷處理句柄中使用什么版本號。需依情況而定,假設僅僅有一個中斷處理句柄訪問該共享資源,那么在中斷處理句柄中僅須要spin_lock和spin_unlock來保護對共享資源的訪問就能夠了。
由于在運行中斷處理句柄期間,不可能被同一CPU上的軟中斷或進程打斷。可是假設有不同的中斷處理句柄訪問該共享資源,那么須要在中斷處理句柄中使用spin_lock_irq和spin_unlock_irq來保護對共享資源的訪問。
在使用spin_lock_irq和spin_unlock_irq的情況下。全然能夠用spin_lock_irqsave和spin_unlock_irqrestore代替。那詳細應該使用哪一個也須要依情況而定,假設能夠確信在對共享資源訪問前中斷是使能的,那么使用spin_lock_irq更好一些。
由于它比spin_lock_irqsave要快一些,可是假設你不能確定是否中斷使能。那么使用spin_lock_irqsave和spin_unlock_irqrestore更好,由于它將恢復訪問共享資源前的中斷標志而不是直接使能中斷。
當然,有些情況下須要在訪問共享資源時必須中斷失效,而訪問完后必須中斷使能。這種情形使用spin_lock_irq和spin_unlock_irq最好。
spin_lock用于阻止在不同CPU上的運行單元對共享資源的同一時候訪問以及不同進程上下文互相搶占導致的對共享資源的非同步訪問,而中斷失效和軟中斷失效卻是為了阻止在同一CPU上軟中斷或中斷對共享資源的非同步訪問。
轉載于:https://www.cnblogs.com/llguanli/p/7140612.html
總結
以上是生活随笔為你收集整理的自旋锁spinlock解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 读书方法(如果努力有用的话,那还要天才干
- 下一篇: input文本框设置移除默认内容(兼容I