一、原子操作
原子操作可以操作指令以原子的方式執(zhí)行,執(zhí)行過程不會(huì)被打斷。
1.1 原子整數(shù)操作
針對(duì)整數(shù)的原子操作只跟對(duì)atomic_t類型的數(shù)據(jù)進(jìn)行處理。原子操作通常是內(nèi)聯(lián)函數(shù),往往是通過內(nèi)嵌匯編指令來實(shí)現(xiàn)的。在編寫代碼時(shí),能使用原子操作時(shí),就盡量不要使用復(fù)雜的加鎖機(jī)制。原子操作給系統(tǒng)帶來的開銷小,對(duì)高速緩存行(cache-line)的影響也小。
1.2 64位原子操作
所有的64位體系結(jié)構(gòu)都提供了atomic64_t類型,以及一組對(duì)應(yīng)的算數(shù)操作方法:
1.3 原子位操作
位操作函數(shù)是對(duì)普通的內(nèi)存地址進(jìn)行操作的:
內(nèi)核還提供了一組與上述操作對(duì)應(yīng)的非原子位函數(shù),不保證原子性,其函數(shù)名字前綴多了兩個(gè)下劃線,執(zhí)行速度可能更快。
二、自旋鎖
Linux內(nèi)核最常見的鎖是自旋鎖(spin lock)。自旋鎖最多只能被一個(gè)可執(zhí)行線程持有。如果一個(gè)執(zhí)行線程試圖獲得一個(gè)被持有的自旋鎖,那么該線程會(huì)一直進(jìn)程忙循環(huán)--旋轉(zhuǎn)--等待鎖重新可用。要是鎖未被爭(zhēng)用,請(qǐng)求鎖的執(zhí)行線程便立即得到它,繼續(xù)執(zhí)行。因此,自旋鎖不應(yīng)該被長(zhǎng)時(shí)間持有,最好小于完成兩次上下文切換的耗時(shí)。
Linux內(nèi)核提供了專門的讀-寫自旋鎖(共享/排斥鎖、并發(fā)/排斥鎖)。一個(gè)或多個(gè)讀任務(wù)可以并發(fā)地持有讀者鎖;寫鎖最多只能被一個(gè)寫任務(wù)持有,而且不能有并發(fā)的讀操作。
三、信號(hào)量
Linux中的信號(hào)量是一種睡眠鎖。如果有一個(gè)任務(wù)試圖獲得一個(gè)已被占用的信號(hào)量時(shí),信號(hào)量會(huì)將其推進(jìn)一個(gè)等待隊(duì)列,然后讓其睡眠。這時(shí)處理器可以執(zhí)行其他代碼。當(dāng)持有信號(hào)量被釋放后,處于等待隊(duì)列的任務(wù)將被喚醒,并獲得該信號(hào)量。信號(hào)量比自旋鎖提供了更好的處理器利用率,但造成了更大的開銷。
信號(hào)量可以同時(shí)允許任意數(shù)量的鎖持有者,根據(jù)該數(shù)量的大小可分為:
- 二值信號(hào)量(或互斥信號(hào)量,數(shù)量為1):
- 計(jì)數(shù)信號(hào)量(數(shù)量大于1)
信號(hào)量也可區(qū)分讀寫信號(hào)量。
四、互斥體
互斥體是指任何可以睡眠的強(qiáng)制互斥鎖,比如使用計(jì)數(shù)為1的信號(hào)量。
一般情況下,除非互斥體不夠用,才使用信號(hào)量。而對(duì)于互斥體和自旋鎖:
五、完成變量
如果在內(nèi)核中一個(gè)任務(wù)需要發(fā)出信號(hào)通知另一個(gè)任務(wù)發(fā)生了某個(gè)特定事件,可以利用完成變量(completion variable)。如果一個(gè)任務(wù)要執(zhí)行一些工作時(shí),另一個(gè)任務(wù)就會(huì)在完成變量上等待。當(dāng)這個(gè)任務(wù)完成工作后,會(huì)使用完成變量去喚醒在等待的任務(wù)。
六 BLK:大內(nèi)核鎖
BLK是一個(gè)全局自旋鎖:
- 持有BLK的任務(wù)可以休眠
- BLK是一種遞歸鎖
- BLK只可以用在進(jìn)程上下文
- 新用戶不允許使用BLK
六、順序鎖
順序鎖(seq鎖),主要依靠一個(gè)序列計(jì)數(shù)器。當(dāng)有疑義的數(shù)據(jù)被寫入時(shí),會(huì)得到一個(gè)鎖,并且序列值會(huì)增加,在讀取數(shù)據(jù)之前和之后,序列號(hào)都會(huì)被讀取。如果序列號(hào)相同則說明讀操作進(jìn)行過程中沒有被寫操作打斷。適用于:
- 數(shù)據(jù)存在很多讀者
- 數(shù)據(jù)寫者很少
- 寫者雖少,但寫優(yōu)先于讀,不允許讀者讓寫者饑餓
- 被保護(hù)的數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單
七、禁止搶占
內(nèi)核搶占代碼使用自旋鎖作為非搶占區(qū)域的標(biāo)記。如果一個(gè)自旋鎖被持有,內(nèi)核便不能進(jìn)行搶占。
某些情況下不需要自旋鎖,但仍需要關(guān)閉內(nèi)核搶占: