linux核心中執行的程式,時刻都要防止併發引起的競態。這將會導致資料結構被破壞,嚴重的時候會引起核心崩潰。所以核心同步技術對核心開發的驅動程式來說非常重要。不懂核心同步技術的人,是寫不出安全健壯的核心驅動程式來的。在學習核心同步技術之前需要掌握一下幾個概念。
1 並行,併發與競態:在smp執行的linux核心是真正的並行執行程式,多個cpu可以同時訪問同一資料結構,而在單處理器的
系統上,核心程式的執行就是併發交錯的執行,看起來像同時執行,乙個cpu上同一時間只能執行一條指令。當正常的核心**訪問一種資料結構的時候被中斷或者搶占,中斷程式或者搶占後執行的核心**也訪問這種資料,在這種情況下,有兩種核心控制路徑訪問資料結構,會發生不一致訪問,這就發生了競態。
2 臨界區:臨界區是訪問一種資料結構資料結構的一段**,這段**有可能會被不同的核心控制路徑執行。核心同步保護的是資料結構而不是**,但實際上實現的同步技術是保護訪問資料結構的**。
3 核心搶占定義:程序在執行核心函式時(包括陷入核心的普通程序與核心執行緒)。即它在核心態執行時,允許發生程序切換。
4 核控制路路徑:核心執行**所處不同的環境,主要分為三種:
(1) 正常的系統呼叫與核心執行緒。特點是可以被中斷,允許睡眠,有程序上下文,current巨集有意義,可以被核心搶占。
(2) 可延遲函式:軟中斷,核心定時器,tasklet。特點是可以被中斷,但是不允許睡眠,沒有程序上下文,current巨集無意義,不可以被核心搶占。
<1> 軟中斷的特點:在smp系統上,相同的軟中斷可以在不同的cpu中同時執行,不同的軟中斷也可以同時執行。在單cpu的系統中,相同的軟中斷不能同時執行,不同的軟中斷也不能同時執行。
<2> 核心定時器:是一種核心預定義的軟中斷,具有軟中斷的所有特徵。
<3> tasklet:也是一種核心預定義的軟中斷,但是採用了一些保護機制,使得有其他軟中斷沒有的特點。相同的tasklet在smp系統中也不能同時執行,不同的tasklet可以smp系統中同時執行。
(3) 中斷處理程式:可以被其他型別的中斷程式所打斷。相同的中斷不能巢狀發生。中斷函式可以寫成非可重入函式。
5 核心執行環境分類:
(1) 不支援核心搶占的單cpu系統
(2) 支援核心搶占的單cpu系統
(3)smp系統
在了解了這些概念後,然後再理清一下核心控制路徑的關係,這對於理解不同的同步技術很重要,下面的情況只針對單cpu的可以發生核心搶占的情況:
1 正常的核心**,可以被中斷程式打斷,也可以被可延遲函式打斷(本質上也是被中斷打斷,因為核心在每隔1ms的節拍中斷處理程式中,據決定是否執行可執行函式)。如果中斷處理程式中或者可延遲函式使另外的乙個程序可執行,並且優先順序高於被打斷的程序,這時被打斷的程序就會失去處理器。發生核心搶占。這樣其他程序就會執行,這個程序有可能有會呼叫這段**,相當於間接打斷了現在的**。所以總結一下:由於中斷,正常的核心**可以被中斷處理程式打斷,可以被可延遲函式間接打斷,由於中斷和核心搶占所以正常的核心**必須是可重入的。(打斷為強制暫停執行,非自願放棄處理器)
2 可延遲函式:可以被中斷處理程式打斷,不可以被其他可延遲函式打斷,因為在同乙個cpu上可延遲函式是順序執行的。
3 中斷處理程式:可以被其他型別中斷打斷,不可以被同型別的中斷打斷。因為發生中斷時,同種型別的中斷被禁止。
linux核心為了應對不同核心控制路徑的**引發的競態的問題,應用了一下幾種核心同步技術:
1 per-cpu變數:最簡單的同步技術,他是資料結構的陣列,系統中的每個cpu都擁有陣列中的乙個元素,而且只有自己才可以操作這個元素,其他的cpu不能夠訪問。但是如果非同步函式也要訪問這個變數的話,就必須進行相關的保護。
2 原子操作: 這種技術主要針對單變數的資料,cpu對乙個變數的訪問可能不是原子的,但是採用atomic_t型別的原子變數,核心可以保證原子的訪問變數。注意的是,操作這種變數只能用核心提供的函式,不能單獨的
操作。3 優化屏障與記憶體屏障:優化屏障:保證編譯器不會混淆在屏障操作之前的彙編指令與屏障之後的彙編指令。記憶體屏障:保證在屏障之後的操作開始執行之前,屏障之前的操作已經完成。
4 自旋鎖: 自旋鎖主要針對smp系統,在單處理器上自旋鎖退化為禁止核心搶占的開關。在smp系統上:spin_lock首先禁止核心搶占,然後原子的測試自旋鎖的裝他。如果為1,那麼跳出,核心控制路徑獲得自旋縮。如果為0,則開啟核心搶占,迴圈測試直到為1.這就是自旋鎖名字的來歷。注意在自旋鎖自旋的時候,可以被搶占。在單處理器系統上:spin_lock除了禁止核心搶占,什麼都不做。自旋鎖使用要點:在中斷與可延遲函式中使用自旋鎖是允許的。但一定要注意死鎖。如果正常核心**與中斷處理程式使用同一把鎖,在正常核心**持有鎖的時候應該禁止中斷,否則就會發生死鎖。可延遲函式與正常核心**使用同一把鎖的時候,在正常核心**或得鎖之時應該禁用可延遲函式。在中斷處理程式與可延遲**中使用同一把鎖的時候,可延遲函式或得鎖之時應該禁止中斷。大體的原則是這樣的:中斷處理函式,可延遲函式,正常核心**三者的打斷能力由大到小。在能力小的**中獲得鎖需要禁止所有能力大的**執行。在單處理器上,雖然瑣只是乙個核心搶占的開關,但是用鎖的方法與smp系統上是一樣的。但是目的不同,smp系統中是為了防止死鎖。單處理器上是為了防止競態,在單處理器上的是不可能發生自旋鎖死鎖的。
其他的同步技術還有:
讀/寫自旋鎖。這個鎖是為了增加核心的併發能力。只要沒有核心控制路徑對資料進行修改,允許多個控制路徑同時讀取同一資料結構。讀/寫操作具有相同的優先順序。
順序鎖:與讀寫鎖類似,但是讀/寫操作有不同的優先順序,讀操作的優先順序低於寫操作。也就是乙個讀程式持有鎖的情況下可以被乙個寫程式打斷。
讀取-複製-更新技術(rcu):為了保護大多數情況下被多個cpu讀的資料結構,這種技術沒有使用加鎖技術
訊號量:使程序可以睡眠的鎖。當程序或得不到鎖的時候睡眠,當釋放鎖的時候,喚醒睡在鎖上的程序。
編寫驅動程式中要靈活運用核心中的同步技術,這樣才能編寫出併發度高,穩定健壯的驅動程式。首先要確定哪些部分是需要保護的,這就需要分析訪問資料的**可能有幾個核心控制路徑並行或者併發執行,結合各個同步技術的特點靈活應用,一般而言能不需要同步的就不要同步,能不加鎖的就不加鎖,因為核心同步必然會引起一定的效能損失。
linux核心學習筆記
核心的配置 a.make s3c2410 deconfig b.make menuconfig 圖形化配置 c.使用廠家給出的配置 生成.config 編譯生成核心,使用如下命令 make vmlinux make uimage 帶頭部 真正核心 1 config 建立生成autoconf.h 供源...
Linux核心學習筆記
2.2 核心原始碼樹 arch 特定體系結構的原始碼 block crypto api crypto 核心原始碼文件 drivers 裝置驅動程式 firmware fs vfs和各種檔案系統 include 核心標頭檔案 init 核心引導和初始化 ipc 程序間通訊 kernel 像排程程式這樣...
Linux核心學習
交叉工具鏈 核心相關知識 linux系統的構成 使用者空間 核心空間 思考 為什麼劃分為兩個層次?目的其實是為保護作業系統,防止應用程式的異常導致作業系統崩潰。核心空間與使用者空間是程式執行的兩種不同狀態,通過系統呼叫和硬體中斷能夠完成從使用者空間到核心空間的轉移。那麼linux的核心由哪些構成呢?...