日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

Linux内核的同步机制---自旋锁

發(fā)布時(shí)間:2025/4/16 linux 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux内核的同步机制---自旋锁 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

自旋鎖的思考:http://bbs.chinaunix.net/thread-2333160-1-1.html

近期在看宋寶華的《設(shè)備驅(qū)動(dòng)開(kāi)發(fā)具體解釋》第二版。看到自旋鎖的部分,有些疑惑。所以來(lái)請(qǐng)教下大家。
以下是我參考一些網(wǎng)絡(luò)上的資料得出的一些想法,不知正確與否。記錄下來(lái)大家討論下:
(1) linux上的自旋鎖有三種實(shí)現(xiàn):
? ?? ?? ? 1. 在單cpu。不可搶占內(nèi)核中,自旋鎖為空操作。
? ?? ?? ? 2. 在單cpu,可搶占內(nèi)核中,自旋鎖實(shí)現(xiàn)為“禁止內(nèi)核搶占”。并不實(shí)現(xiàn)“自旋”。
? ?? ?? ? 3. 在多cpu,可搶占內(nèi)核中。自旋鎖實(shí)現(xiàn)為“禁止內(nèi)核搶占” + “自旋”。
(2) 關(guān)于搶占式內(nèi)核與非搶占式內(nèi)核:
? ?? ?? ? 在非搶占式內(nèi)核中,假設(shè)一個(gè)進(jìn)程在內(nèi)核態(tài)執(zhí)行,其僅僅有在下面兩種情況會(huì)被切換:
? ?? ?? ? 1.??其執(zhí)行完畢(返回用戶(hù)空間)
? ?? ?? ? 2.??主動(dòng)讓出cpu(即主動(dòng)調(diào)用schedule或內(nèi)核中的任務(wù)堵塞——這相同也會(huì)導(dǎo)致調(diào)用schedule)

? ?? ?? ? 在搶占式內(nèi)核中,假設(shè)一個(gè)進(jìn)程在內(nèi)核態(tài)執(zhí)行。其僅僅有在下面四種情況會(huì)被切換:
? ?? ?? ? 1.??其執(zhí)行完畢(返回用戶(hù)空間)
? ?? ?? ? 2.??主動(dòng)讓出cpu(即主動(dòng)調(diào)用schedule或內(nèi)核中的任務(wù)堵塞——這相同也會(huì)導(dǎo)致調(diào)用schedule)
? ?? ?? ? 3.??當(dāng)從中斷處理程序正在運(yùn)行,且返回內(nèi)核空間之前(此時(shí)可搶占標(biāo)志premptcount須為0) 。
? ?? ?? ? 4.??當(dāng)內(nèi)核代碼再一次具有可搶占性的時(shí)候。如解鎖及使能軟中斷等。

? ?? ?? ?在宋寶華的書(shū)中,有提到在使用自旋鎖時(shí)。要避免用來(lái)保護(hù)“包括引起堵塞的代碼”。由于堵塞意味著要進(jìn)行進(jìn)程的切換。這點(diǎn)讓我非常迷惑。由于在可搶占式內(nèi)核中使用自旋鎖,是“禁止內(nèi)核搶占”的,既然“禁止內(nèi)核搶占”怎么又會(huì)發(fā)生進(jìn)程的切換呢?
? ?? ?? ?如今我是這么想的:禁止內(nèi)核搶占僅僅是關(guān)閉“可搶占標(biāo)志”。而不是禁止進(jìn)程切換。顯式使用schedule或進(jìn)程堵塞(此也會(huì)導(dǎo)致調(diào)用schedule)時(shí),還是會(huì)發(fā)生進(jìn)程調(diào)度的。

? ?? ?? ?這里補(bǔ)充一些想法:宋寶華的書(shū)上說(shuō),在使用自旋鎖保護(hù)臨界區(qū)時(shí)。如臨界區(qū)中因“包括引起堵塞代碼”而引發(fā)堵塞,從而引起進(jìn)程切換后,若還有一進(jìn)程企圖獲得本自旋鎖。死鎖會(huì)發(fā)生。
? ?? ?? ?個(gè)人感覺(jué)。唯獨(dú)在多cpu。內(nèi)核可搶占的情況會(huì)發(fā)生死鎖。而在單cpu。內(nèi)核可搶占或不可搶占的情況,不會(huì)發(fā)生死鎖,但此時(shí)自旋鎖失效(即無(wú)法實(shí)現(xiàn)保護(hù)臨界區(qū)的功能)。這是由于多cpu可搶占內(nèi)核實(shí)現(xiàn)了“自旋”,所以會(huì)導(dǎo)致死鎖。而單cpu可搶占或不可搶占內(nèi)核,沒(méi)有實(shí)現(xiàn)“自旋”。不過(guò)“禁止內(nèi)核搶占”,因此不會(huì)發(fā)生死鎖。可是會(huì)發(fā)生無(wú)保護(hù)的反復(fù)進(jìn)入臨界區(qū)的情況(即無(wú)法實(shí)現(xiàn)保護(hù)臨界區(qū)的功能)。

以上觀點(diǎn)僅僅是個(gè)人想法,不當(dāng)之處,還請(qǐng)各位指出,謝謝。



五、自旋鎖(spinlock)

自旋鎖與相互排斥鎖有點(diǎn)類(lèi)似,僅僅是自旋鎖不會(huì)引起調(diào)用者睡眠。假設(shè)自旋鎖已經(jīng)被別的運(yùn)行單元保持,調(diào)用者就一直循環(huán)在那里看是否該自旋鎖的保持者已經(jīng)釋放了鎖,"自旋"一詞就是因此而得名。

因?yàn)樽孕i使用者一般保持鎖時(shí)間很短,因此選擇自旋而不是睡眠是很必要的,自旋鎖的效率遠(yuǎn)高于相互排斥鎖。

信號(hào)量和讀寫(xiě)信號(hào)量適合于保持時(shí)間較長(zhǎng)的情況,它們會(huì)導(dǎo)致調(diào)用者睡眠。因此僅僅能在進(jìn)程上下文使用(_trylock的變種可以在中斷上下文使用),而自旋鎖適合于保持時(shí)間很短的情況,它可以在不論什么上下文使用。

假設(shè)被保護(hù)的共享資源僅僅在進(jìn)程上下文訪問(wèn),使用信號(hào)量保護(hù)該共享資源很合適,假設(shè)對(duì)共巷資源的訪問(wèn)時(shí)間很短,自旋鎖也能夠。可是假設(shè)被保護(hù)的共享資源須要在中斷上下文訪問(wèn)(包含底半部即中斷處理句柄和頂半部即軟中斷)。就必須使用自旋鎖。

自旋鎖保持期間是搶占失效的,而信號(hào)量和讀寫(xiě)信號(hào)量保持期間是能夠被搶占的。自旋鎖僅僅有在內(nèi)核可搶占或SMP的情況下才真正須要,在單CPU且不可搶占的內(nèi)核下,自旋鎖的全部操作都是空操作。

跟相互排斥鎖一樣,一個(gè)運(yùn)行單元要想訪問(wèn)被自旋鎖保護(hù)的共享資源,必須先得到鎖,在訪問(wèn)完共享資源后,必須釋放鎖。假設(shè)在獲取自旋鎖時(shí),沒(méi)有不論什么運(yùn)行單元保持該鎖,那么將馬上得到鎖。假設(shè)在獲取自旋鎖時(shí)鎖已經(jīng)有保持者,那么獲取鎖操作將自旋在那里,直到該自旋鎖的保持者釋放了鎖

不管是相互排斥鎖。還是自旋鎖,在不論什么時(shí)刻,最多僅僅能有一個(gè)保持者,也就說(shuō),在不論什么時(shí)刻最多僅僅能有一個(gè)運(yùn)行單元獲得鎖。

自旋鎖的API有:

spin_lock_init(x)

該宏用于初始化自旋鎖x。自旋鎖在真正使用前必須先初始化。該宏用于動(dòng)態(tài)初始化。

DEFINE_SPINLOCK(x)

該宏聲明一個(gè)自旋鎖x并初始化它。該宏在2.6.11中第一次被定義,在先前的內(nèi)核中并沒(méi)有該宏。

SPIN_LOCK_UNLOCKED

該宏用于靜態(tài)初始化一個(gè)自旋鎖。

DEFINE_SPINLOCK(x)等同于spinlock_t x = SPIN_LOCK_UNLOCKEDspin_is_locked(x)

該宏用于推斷自旋鎖x是否已經(jīng)被某運(yùn)行單元保持(即被鎖),假設(shè)是,返回真,否則返回假。

spin_unlock_wait(x)

該宏用于等待自旋鎖x變得沒(méi)有被不論什么運(yùn)行單元保持,假設(shè)沒(méi)有不論什么運(yùn)行單元保持該自旋鎖,該宏馬上返回。否則將循環(huán)在那里。直到該自旋鎖被保持者釋放。

spin_trylock(lock)

該宏盡力獲得自旋鎖lock,假設(shè)能馬上獲得鎖,它獲得鎖并返回真,否則不能馬上獲得鎖。馬上返回假。它不會(huì)自旋等待lock被釋放。

spin_lock(lock)

該宏用于獲得自旋鎖lock,假設(shè)可以立即獲得鎖,它就立即返回,否則,它將自旋在那里,直到該自旋鎖的保持者釋放。這時(shí),它獲得鎖并返回。總之。僅僅有它獲得鎖才返回。

spin_lock_irqsave(lock, flags)

該宏獲得自旋鎖的同一時(shí)候把標(biāo)志寄存器的值保存到變量flags中并失效本地中斷。

spin_lock_irq(lock)

該宏類(lèi)似于spin_lock_irqsave,僅僅是該宏不保存標(biāo)志寄存器的值。

spin_lock_bh(lock)

該宏在得到自旋鎖的同一時(shí)候失效本地軟中斷。

spin_unlock(lock)

該宏釋放自旋鎖lock,它與spin_trylock或spin_lock配對(duì)使用。假設(shè)spin_trylock返回假,表明沒(méi)有獲得自旋鎖,因此不必使用spin_unlock釋放。

spin_unlock_irqrestore(lock, flags)

該宏釋放自旋鎖lock的同一時(shí)候。也恢復(fù)標(biāo)志寄存器的值為變量flags保存的值。

它與spin_lock_irqsave配對(duì)使用。

spin_unlock_irq(lock)

該宏釋放自旋鎖lock的同一時(shí)候,也使能本地中斷。它與spin_lock_irq配相應(yīng)用

spin_unlock_bh(lock)

該宏釋放自旋鎖lock的同一時(shí)候,也使能本地的軟中斷。

它與spin_lock_bh配對(duì)使用。

spin_trylock_irqsave(lock, flags)??
該宏假設(shè)獲得自旋鎖lock。它也將保存標(biāo)志寄存器的值到變量flags中,而且失效本地中斷,假設(shè)沒(méi)有獲得鎖,它什么也不做。

因此假設(shè)可以馬上獲得鎖。它等同于spin_lock_irqsave,假設(shè)不能獲得鎖。它等同于spin_trylock。

假設(shè)該宏獲得自旋鎖lock,那須要使用spin_unlock_irqrestore來(lái)釋放。

spin_trylock_irq(lock)

該宏類(lèi)似于spin_trylock_irqsave,僅僅是該宏不保存標(biāo)志寄存器。

假設(shè)該宏獲得自旋鎖lock,須要使用spin_unlock_irq來(lái)釋放。

spin_trylock_bh(lock)

該宏假設(shè)獲得了自旋鎖。它也將失效本地軟中斷。假設(shè)得不到鎖。它什么也不做。因此,假設(shè)得到了鎖,它等同于spin_lock_bh,假設(shè)得不到鎖,它等同于spin_trylock。假設(shè)該宏得到了自旋鎖。須要使用spin_unlock_bh來(lái)釋放。

spin_can_lock(lock)

該宏用于推斷自旋鎖lock是否可以被鎖,它實(shí)際是spin_is_locked取反。假設(shè)lock沒(méi)有被鎖,它返回真,否則,返回假。該宏在2.6.11中第一次被定義,在先前的內(nèi)核中并沒(méi)有該宏。

獲得自旋鎖和釋放自旋鎖有好幾個(gè)版本號(hào),因此讓讀者知道在什么樣的情況下使用什么版本號(hào)的獲得和釋放鎖的宏是很必要的。

假設(shè)被保護(hù)的共享資源僅僅在進(jìn)程上下文訪問(wèn)和軟中斷上下文訪問(wèn),那么當(dāng)在進(jìn)程上下文訪問(wèn)共享資源時(shí)。可能被軟中斷打斷,從而可能進(jìn)入軟中斷上下文來(lái)對(duì)被保護(hù)的共享資源訪問(wèn)。因此對(duì)于這樣的情況,對(duì)共享資源的訪問(wèn)必須使用spin_lock_bh和spin_unlock_bh來(lái)保護(hù)

當(dāng)然使用spin_lock_irq和spin_unlock_irq以及spin_lock_irqsave和spin_unlock_irqrestore也能夠。它們失效了本地硬中斷,失效硬中斷隱式地也失效了軟中斷。可是使用spin_lock_bh和spin_unlock_bh是最恰當(dāng)?shù)摹K绕渌鼉蓚€(gè)快

假設(shè)被保護(hù)的共享資源僅僅在進(jìn)程上下文和tasklet或timer上下文訪問(wèn)。那么應(yīng)該使用與上面情況同樣的獲得和釋放鎖的宏,由于tasklet和timer是用軟中斷實(shí)現(xiàn)的。

假設(shè)被保護(hù)的共享資源僅僅在一個(gè)tasklet或timer上下文訪問(wèn),那么不須要不論什么自旋鎖保護(hù),由于同一個(gè)tasklet或timer僅僅能在一個(gè)CPU上執(zhí)行,即使是在SMP環(huán)境下也是如此。實(shí)際上tasklet在調(diào)用tasklet_schedule標(biāo)記其須要被調(diào)度時(shí)已經(jīng)把該tasklet綁定到當(dāng)前CPU,因此同一個(gè)tasklet決不可能同一時(shí)候在其它CPU上執(zhí)行。

timer也是在其被使用add_timer加入到timer隊(duì)列中時(shí)已經(jīng)被幫定到當(dāng)前CPU,所以同一個(gè)timer絕不可能執(zhí)行在其它CPU上。

當(dāng)然同一個(gè)tasklet有兩個(gè)實(shí)例同一時(shí)候執(zhí)行在同一個(gè)CPU就更不可能了。

假設(shè)被保護(hù)的共享資源僅僅在兩個(gè)或多個(gè)tasklet或timer上下文訪問(wèn),那么對(duì)共享資源的訪問(wèn)僅須要用spin_lock和spin_unlock來(lái)保護(hù),不必使用_bh版本號(hào),由于當(dāng)tasklet或timer執(zhí)行時(shí),不可能有其它tasklet或timer在當(dāng)前CPU上執(zhí)行。

假設(shè)被保護(hù)的共享資源僅僅在一個(gè)軟中斷(tasklet和timer除外)上下文訪問(wèn),那么這個(gè)共享資源須要用spin_lock和spin_unlock來(lái)保護(hù),由于相同的軟中斷能夠同一時(shí)候在不同的CPU上執(zhí)行。

假設(shè)被保護(hù)的共享資源在兩個(gè)或多個(gè)軟中斷上下文訪問(wèn),那么這個(gè)共享資源當(dāng)然更須要用spin_lock和spin_unlock來(lái)保護(hù),不同的軟中斷可以同一時(shí)候在不同的CPU上執(zhí)行。

假設(shè)被保護(hù)的共享資源在軟中斷(包含tasklet和timer)或進(jìn)程上下文和硬中斷上下文訪問(wèn),那么在軟中斷或進(jìn)程上下文訪問(wèn)期間。可能被硬中斷打斷,從而進(jìn)入硬中斷上下文對(duì)共享資源進(jìn)行訪問(wèn)。因此。在進(jìn)程或軟中斷上下文須要使用spin_lock_irq和spin_unlock_irq來(lái)保護(hù)對(duì)共享資源的訪問(wèn)。

而在中斷處理句柄中使用什么版本號(hào)。需依情況而定,假設(shè)僅僅有一個(gè)中斷處理句柄訪問(wèn)該共享資源,那么在中斷處理句柄中僅須要spin_lock和spin_unlock來(lái)保護(hù)對(duì)共享資源的訪問(wèn)就能夠了。

由于在運(yùn)行中斷處理句柄期間,不可能被同一CPU上的軟中斷或進(jìn)程打斷。可是假設(shè)有不同的中斷處理句柄訪問(wèn)該共享資源。那么須要在中斷處理句柄中使用spin_lock_irq和spin_unlock_irq來(lái)保護(hù)對(duì)共享資源的訪問(wèn)。

在使用spin_lock_irq和spin_unlock_irq的情況下,全然能夠用spin_lock_irqsave和spin_unlock_irqrestore代替,那詳細(xì)應(yīng)該使用哪一個(gè)也須要依情況而定。假設(shè)能夠確信在對(duì)共享資源訪問(wèn)前中斷是使能的,那么使用spin_lock_irq更好一些。

由于它比spin_lock_irqsave要快一些。可是假設(shè)你不能確定是否中斷使能,那么使用spin_lock_irqsave和spin_unlock_irqrestore更好,由于它將恢復(fù)訪問(wèn)共享資源前的中斷標(biāo)志而不是直接使能中斷。

當(dāng)然。有些情況下須要在訪問(wèn)共享資源時(shí)必須中斷失效。而訪問(wèn)完后必須中斷使能,這種情形使用spin_lock_irq和spin_unlock_irq最好。

須要特別提醒讀者,spin_lock用于阻止在不同CPU上的運(yùn)行單元對(duì)共享資源的同一時(shí)候訪問(wèn)以及不同進(jìn)程上下文互相搶占導(dǎo)致的對(duì)共享資源的非同步訪問(wèn)。而中斷失效和軟中斷失效卻是為了阻止在同一CPU上軟中斷或中斷對(duì)共享資源的非同步訪問(wèn)。

參考資料

Kernel Locking Techniques,http://www.linuxjournal.com/article/5833

Redhat 9.0 kernel source tree

kernel.org 2.6.12 source tree

Linux 2.6內(nèi)核中新的鎖機(jī)制--RCU(Read-Copy Update),

http://www.ibm.com/developerworks/cn/linux/l-rcu/

Unreliable Guide To Locking.

總結(jié)

以上是生活随笔為你收集整理的Linux内核的同步机制---自旋锁的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。