1. 程式人生 > >關於核心中spinlock的一些個人理解

關於核心中spinlock的一些個人理解


在這裡,我主要把自己對核心中spinlock的一些理解寫出來,並不是要告訴大傢什麼(因為我對我所說的也不能確定),而是希望大家對我的這些理解對的地方給我肯定,錯誤的地方給我指出。

和spinlock 相關的檔案主要有兩個,一個是include/linux/spinlock.h,主要是提供關於和硬體無關的spinlock的幾個對外主函式,一個是 include/asm-XXX/spinlock.h,用來提供和硬體相關的功能函式。另外,在2.6的核心中,又多了一個檔案, include/linux/preempt.h,為新增加的搶佔式多工功能提供一些服務。

spinlock的作用:spinlock系列函式主要用於保護臨界資料(非常重要的資料)不被同時訪問(給臨界資料加鎖),用以達到多工的同步。如果一個數據當前不可訪問,那麼就一直等,直到可以訪問為止。

spinlock 函式的使用前提:首先,spinklock函式只能使用在核心中,或者說只能使用在核心狀態下,在2.6以前的核心是不可搶佔的,也就是說,當運行於核心狀態下時,是不容許切換到其他程序的

。而在2.6以後的核心中,編譯核心的時候多了一個選項,可以配置核心是否可以被搶佔,這也就是為什麼在2.6的核心中多了一個preempt.h的原因。

spinlock主要包含以下幾個函式:
spin_lock
spin_unlock
spin_lock_irqsave
spin_lock_irq
spin_unlock_irqrestore
spin_unlock_irq
另外還有其他很多,如關於讀者寫者的一套函式,關於bottom half一套函式(關於bottom half的程式碼我還沒有讀到),還有還提供了一套用bit實現加鎖的函式,由於大概意思都相同,所以我這裡就不說了(只想簡單說說,沒想到東西還挺多,我的手都快凍僵了,江南的冬天真的受不了:)
spinlock函式根據機器的配置分為兩套,單CPU和多CPU,先來看看單CPU的情況。
在單CPU的情況下,spin_lock和spin_unlock函式都被定義成空操作(do { } while(0)),這是因為我們上面說的,核心不可以被搶佔的原因。所以,在單CPU的情況下,只要你能夠保證你要保護的臨界資料不會在中斷中用到的話,那麼你的資料已經是受保護的了,不需要做任何操作。在2.6核心中,這兩個函式就不再這麼簡單了,因為核心也有可能被其他程式中斷,所以要保護資料,還要讓排程程式暫時不排程此段程式,也就是說,暫時禁止搶佔式任務排程功能,所以在上面兩個函式中分別多了一個






需要澄清的是,互斥手段的選擇,不是根據臨界區的大小,而是根據臨界區的性質,以及
有哪些部分的程式碼,即哪些核心執行路徑來爭奪。

從嚴格意義上說,semaphore和spinlock_XXX屬於不同層次的互斥手段,前者的
實現有賴於後者,這有點象HTTP和TCP的關係,都是協議,但層次是不同的。

先說semaphore,它是程序級的,用於多個程序之間對資源的互斥,雖然也是在
核心中,但是該核心執行路徑是以程序的身份,代表程序來爭奪資源的。如果
競爭不上,會有context switch,程序可以去sleep,但CPU不會停,會接著執行
其他的執行路徑。從概念上說,這和單CPU或多CPU沒有直接的關係,只是在
semaphore本身的實現上,為了保證semaphore結構存取的原子性,在多CPU中需要
spinlock來互斥。

在核心中,更多的是要保持核心各個執行路徑之間的資料訪問互斥,這是最基本的
互斥問題,即保持資料修改的原子性。semaphore的實現,也要依賴這個。在單CPU
中,主要是中斷和bottom_half的問題,因此,開關中斷就可以了。在多CPU中,
又加上了其他CPU的干擾,因此需要spinlock來幫助。這兩個部分結合起來,
就形成了spinlock_XXX。它的特點是,一旦CPU進入了spinlock_XXX,它就不會
幹別的,而是一直空轉,直到鎖定成功為止。因此,這就決定了被
spinlock_XXX鎖住的臨界區不能停,更不能context switch,要存取完資料後趕快
出來,以便其他的在空轉的執行路徑能夠獲得spinlock。這也是spinlock的原則
所在。如果當前執行路徑一定要進行context switch,那就要在schedule()之前
釋放spinlock,否則,容易死鎖。因為在中斷和bh中,沒有context,無法進行
context switch,只能空轉等待spinlock,你context switch走了,誰知道猴年
馬月才能回來。

因為spinlock的原意和目的就是保證資料修改的原子性,因此也沒有理由在spinlock
鎖住的臨界區中停留。

spinlock_XXX有很多形式,有


那麼,在什麼情況下具體用哪個呢?這要看是在什麼核心執行路徑中,以及要與哪些核心
執行路徑相互斥。我們知道,核心中的執行路徑主要有:

這樣,考慮這四個方面的因素,通過判斷我們要互斥的資料會被這四個因素中
的哪幾個來存取,就可以決定具體使用哪種形式的spinlock。如果只要和其他CPU
互斥,就要用spin_lock/spin_unlock,如果要和irq及其他CPU互斥,就要用
spin_lock_irq/spin_unlock_irq,如果既要和irq及其他CPU互斥,又要儲存
EFLAG的狀態,就要用spin_lock_irqsave/spin_unlock_irqrestore,如果
要和bh及其他CPU互斥,就要用spin_lock_bh/spin_unlock_bh,如果不需要和
其他CPU互斥,只要和irq互斥,則用local_irq_disable/local_irq_enable,
如果不需要和其他CPU互斥,只要和bh互斥,則用local_bh_disable/local_bh_enable,
等等。值得指出的是,對同一個資料的互斥,在不同的核心執行路徑中,
所用的形式有可能不同(見下面的例子)。

舉一個例子。在中斷部分中有一個irq_desc_t型別的結構陣列變數irq_desc[],
該陣列每個成員對應一個irq的描述結構,裡面有該irq的響應函式等。
在irq_desc_t結構中有一個spinlock,用來保證存取(修改)的互斥。

對於具體一個irq成員,irq_desc[irq],對其存取的核心執行路徑有兩個,一是
在設定該irq的響應函式時(setup_irq),這通常發生在module的初始化階段,或
系統的初始化階段;二是在中斷響應函式中(do_IRQ)。程式碼如下:



在setup_irq()中,因為其他CPU可能同時在執行setup_irq(),或者在執行setup_irq()時,
本地irq中斷來了,要執行do_IRQ()以修改desc->status。為了同時防止來自其他CPU和
本地irq中斷的干擾,如[1][2][3]處所示,使用了spin_lock_irqsave/spin_unlock_irqrestore()

而在do_IRQ()中,因為do_IRQ()本身是在中斷中,而且此時還沒有開中斷,本CPU中沒有
什麼可以中斷其執行,其他CPU則有可能在執行setup_irq(),或者也在中斷中,但這二者
對本地do_IRQ()的影響沒有區別,都是來自其他CPU的干擾,因此只需要用spin_lock/spin_unlock,
如[4][5][6][7]處所示。值得注意的是[5]處,先釋放該spinlock,再呼叫具體的響應函式。

再舉個例子:



這裡,對tasklet_hi_vec[cpu]的修改,不存在CPU之間的競爭,因為每個CPU有各自獨立的資料,
所以只要防止irq的干擾,用local_irq_disable/local_irq_enable即可,如[8][9][10][11]處
所示。 
 

相關推薦

關於心中spinlock一些個人理解

在這裡,我主要把自己對核心中spinlock的一些理解寫出來,並不是要告訴大傢什麼(因為我對我所說的也不能確定),而是希望大家對我的這些理解對的地方給我肯定,錯誤的地方給我指出。和spinlock 相關的檔案主要有兩個,一個是include/linux/spinlock.h,

數據庫的事物隔離級別以及鎖的一些個人理解

nco 理解 rep 查詢 釋放 如果 就是 時間 server 數據庫的 基本分為 共享鎖和排它鎖 排它鎖顧名思義,不能和其他任何所共存。 以SqlServer中某一行數據為例, 特殊的,WithNoLock 這個是不給數據加上任何鎖,所以根本和鎖沒關系 再說update

Servlet一些個人理解

創建 http src .cn 容器管理 mage 進行 路徑 配置 一、什麽是Servlet   1.Servlet是一個基於Java技術的動態網頁技術,運行在服務器端,由Servlet容器管理,用於生成動態內容,是jsp( servlet進行網頁開發非常的繁瑣,所以現在

RBF神經網路的一些個人理解

RBF徑向基函式,取值僅依賴於離原點距離的實值函式,任何滿足這種特性的函式就叫徑向基函式。一般採用歐氏距離,也可以用其他距離。 簡介: 是單隱層的前饋神經網路,使用徑向基函式作為隱層神經元的啟用函式,輸出層則是對隱層神經元輸出的線性組合(理論上可以設定多個隱層,但一般只設計一個隱層)。所

關於Dagger2的一些個人理解

寫作目的 現在基本上有一些規模的專案,都使用了Dagger2,也不是裝13,個人感覺也的確是大勢所趨,Dagger2的確有它的優勢。藉著手上的專案,學習了一下Dagger2,打算用在公司的專案中。今天就來以自己初學者的角度來談談dagger2的認識。 問題由來 我是目前是移動

讀O目標KR關鍵結果的一些個人理解

O目標KR關鍵結果 為了完成一個目標,需要完成幾個或者多個關鍵的結果來驗證。 書的開頭寫的是一些理論,有印象的東西還是從漢娜和傑克的公司來說,賣茶葉的公司。聯絡著茶農和可以產生消費的餐館和供應商,在未遇到OKR的實踐中拉斐爾之前,漢娜和傑克為了公司存貨,都在努力嘗試著他們各自認為可以讓公司存活的方式,但是

關於貝葉斯的一些個人理解

關於貝葉斯分類器的一些理解 參考西瓜書及一些論壇資料 首先明白咱們用貝葉斯***分類***器想幹什麼: 例如:有一個細胞切片,通過收集樣本,得到一些良性細胞的特徵和噁心細胞的特徵。這時如果出現了一個新的細胞,我們希望可以通過從這個新細胞上面得到一些特徵來判斷這個

敏捷開發及一些個人理解

簡單的說下敏捷開發的一些知識: 敏捷開發以使用者的需求進化為核心,採用迭代、循序漸進的方法進行軟體開發。在敏捷開發中,軟體專案在構建初期被切分成多個子專案,各個子專案的成果都經過測試,具備可視、可整合和可執行使用的特徵。換言之,就是把一個大專案分為多個相互聯絡,但也可獨立執

關於maven的一些個人理解

一、什麼是Maven?maven是一個專案構建和管理的工具,提供了幫助管理構建、文件、報告、依賴、釋出、分發的方法。可以方便的編譯程式碼、進行依賴管理、管理二進位制庫等等。如果沒有Maven,你可能不得不經歷的過程!!如果使用了spring,去spring的官網下載jar包;

關於JDBC的一些個人理解

最近回顧了java基礎方面的一些東西,這裡就jdbc寫一個個人總結,如果有不對的地方,歡迎各位批評指正。 1.什麼是jdbc? 簡單地說,jdbc技術就是用來對資料庫做操作的。它為應用程式訪問資料庫提供了統一的介面,遮蔽了各種資料庫之間的異構性,保證了程式的可移植性。在jdbc中開發

spring+mybatis通用dao層、service層的一些個人理解與實現

1、現在的絕大多數web應用,通常都以action、service、dao三層去組織程式碼,這樣劃分結構很清晰,分工明確 2、一般情況下,我們會把事務控制在service層。 3、action和dao層,會使用一些框架技術。比如action層可能選擇有springmvc、struts等,dao層有hibe

關於大資料的一些個人理解

一般網站大概幾TB的資料量,這個數量級用mysql這樣傳統的資料庫還ok, 但如果再大,查詢起來就很慢,如果你想搜尋個關鍵詞,等半小時出不來結果,就很鬱悶。 所以大資料經常是上百TB,PB這樣的量級,並且用傳統的方法不能快速處理,必須用分散式的計算與儲存方法, 這樣才好意思說自己是大資料,這是其一。 其二,

Recyclerview的一些個人理解與使用(三)列表中的計時器

昨天專案升級了一版後,手頭又有了些許閒餘時間,剛好之前看到群裡的小夥伴由於有個定時器的需求,加入到Recyclerview中遇到了許多麻煩,今天剛好寫一個demo練練手,看看自己能否解決這個問題。 按照一般的列表Recyclerview來做,先

關於Bean\Entity\Model\POJO的一些個人理解

轉自:https://www.cnblogs.com/LiuChunfu/p/5574565.html本文沒有長篇累牘的,嚴格的,標準的表述,只是我在開發過程中,讀書過程中的一些個人理解,可能不太準備,但是我覺得應該是最方便初學者理解的吧?一、Bean對於Bean而言,我的理

Recyclerview的一些個人理解與使用(二)實現一個簡單的列表介面

公司專案前一段時間有些忙 ,忙完後趕緊就來寫下了這篇文章,上次的文章 中,我們對Recyclerview進行了一個基礎的封裝,這次我們就用上次的封裝實現一個最簡單的Recyclerview。 先來看看效果圖 一個簡單的列表。下面是佈局檔案:

關於IOC容器的一些個人理解

它的 依賴註入 測試 代碼 工作 pan 你們 net tof 原文:關於IOC容器的一些個人理解一丶前言   下面是本人對於IOC容器的一些個人理解,希望能幫到初學者認識IOC,如有理解得不對的地方歡迎指正,也讓我學學。 二丶IOC是什麽,它是幹嘛的?   IOC只

關於LaaS,PaaS,SaaS一些個人理解

放心 服務器 soft 程序 nbsp sin php 管理 比較 關於LaaS,PaaS,SaaS一些個人的理解 其實如果從整個程序運營的角度來考慮比較好 第一個LaaS 這個也叫做Haas 就是硬件或者基礎設置即服務 比如現在的 aws azure 阿裏雲

計算機網路面試一些問題,個人理解

# 三次握手和四次揮手 定義或者說想要解決的問題:源主機想要與目的主機進行cp連線時,需要三次握手過程才能建立連線。源主機在與目的主機建立連線後,想要斷開連線就需要四次揮手的過程。 ------- 詳細過程:三次握手:首先源主機需要通過socket傳送一個SYN(SYN置1,synchr

個人理解一些東西

程式設計中常見的各種鉤子(hook) 個人理解就是一種在執行某種任務訊息時,可以在其執行的前後新增一個hook程式來對其進行一些相應的控制,比如傳送請求前,傳送請求後等,就是一種在某個程式功能中嵌入某種控制的程式 Js中的物件跟Python的字典dict很相似

個人對Redis的一些簡單理解

這是個人在這邊寫的第二篇文章 畢業一年半了,從合肥轉戰來到上海,最大變化的是頭髮稀少了好多...... 今天寫寫redis,以及叢集方面的東西    redis的作用百度很多,確實相比一些佔用jvm記憶體的一些快取資料作用要強大的多,光效能這方面就完爆了.. 我也是一名r