Linux 裝置驅動併發控制簡述

2021-08-14 02:15:56 字數 2773 閱讀 7509

答案 :在linux中會遇到多個程序對共享資源的併發訪問,併發訪問會導致競態的發生,所以需要併發控制機制。

併發與競態是指多個執行單位同時並行的被執行,而併發的執行單位對共享資源的訪問很容易導致競態

2.1 對稱多處理器 (smp系統) 的多個cpu

:多個cpu共用同一條系統匯流排,因此可以訪問共同的外設和儲存器,此時多個核的程序、中斷可能交叉實現併發競態度。

2.2 單cpu內程序與搶占它的程序

:linux 2.6 之後核心支援核心搶占排程。

2.3 中斷與程序之間

:單核 多核 的程序、中斷相互競爭

訪問共享資源的**區叫 臨界區,臨界區需要被 併發控制機制加以保護,也叫互斥機制,包括:中斷遮蔽、原子操作、自旋鎖、訊號量、互斥體等。也就是在乙個執行單元在訪問共享資源的時候,其他的執行單元禁止訪問該共享資源。

4.1 概念:

使得中斷與程序之間的併發不再發生,並且,因為linux 核心之間程序排程都是依賴中斷實現的,因此,也會使得核心中程序之間併發不再發生。

4.2 使用:

local_irq_disable();

...臨界區

...local_irq_enable();

4.3 注意:因為在linux中的非同步i/o,程序排程等操作都依賴於中斷,中斷對核心

執行十分重要,在遮蔽中斷期間,核心中所有的中斷都無法得到處理,所以長時間的遮蔽中斷時不可取的。

5.1 概念:可以使得對乙個整型資料的修改是排他性的,原子操作分別針對 位 和

整型變數,位和整型變數原子操作都以來於底層cpu的原子操作,對於arm處理器而言,底層使用 ldtex 和 strex指令。原子操作就是將ldtex 和 strex搭配使用,使得某些變數或者位同一時間只能有乙個實體操作,

5.2 ldtex 和 strex:

ldrex rx ,[ry] : 讀取暫存器ry指向的4位元組記憶體值,將其儲存到rx暫存器中,同時標記ry指向的記憶體為 獨佔訪問,

strex rx ,ry ,[rz]: 更新記憶體數值

6.1 概念:

自旋鎖操作是基於原子操作的,某個執行單位的**需要先執行乙個原子操作,該操作測試並設定了某個記憶體變數(鎖),然後訪問臨界區資源,在該執行單位釋放釋放前面設定的記憶體變數(鎖)之前,其他的執行單位不能訪問獲得這個記憶體變數(鎖),自然就不能訪問臨界區資源,其他執行單位會一直測試並設定 該鎖 ,直到
可以獲取該鎖為止。

6.2 使用:

spinlock_t lock; 定義乙個自旋鎖

spin_lock_init(&lock); 初始化自旋鎖

spin_lock(&lock); 獲得自旋鎖

...臨界區...

spin_unlock(&lock); 釋放自旋鎖

6.3 注意:

6.3.1 初級的自旋鎖可以保證臨界區不受其他cpu和本cpu內的搶占程序的打擾,但是無法避免中斷和bh的影響,此時需要衍生的自旋鎖,大致就是 開啟自旋鎖+開啟中斷遮蔽、釋放自旋鎖+關閉中斷遮蔽。。。等等

6.3.2

cpu在不停的嘗試獲取自旋鎖期間不做其他工作,只是等待獲取鎖,因此,只有在占用鎖時間很短的情況下使用自旋鎖才更加合理,當臨界區很大時,需要較長時間的占用鎖,會降低系統速度。

6.3.3

當乙個執行單位持有鎖期間,在釋放鎖之前,遞迴再一次的嘗試獲取鎖,將會導致cpu鎖死

6.3.4

在自旋鎖鎖定期間不可以呼叫 可能引起程序排程的函式,因為程序排程有阻塞操作,如果獲得自旋鎖之後再阻塞,可能會導致核心崩潰。如呼叫 copy_to_user copy_from_user kmalloc msleep 等等。

7.1 概念:

和訊號量類似,訊號量的值可以是0、1或者n 如果訊號量的值大於0 該程序繼續執行,如果訊號量的值等於0,那個該程序設定為等待狀態,排入訊號等到佇列,知道系統喚醒

7.2 使用:struct mutex my_mutex;

定義mutex

mutex_init(&my_mutex);初始化mutex

mutex_lock(&my_mutex);獲取mutex

...臨界區...

mutex_unlock(&my_mutex);釋放mutex

7.3 注意:

互斥體是程序級,用於多個程序之間對資源的互斥,如果競爭失敗,會發生上下文的 切換,當前程序進入睡眠狀態,cpu執行其他程序,因為程序上下文切換開銷很大,所以,只有當程序占用資源較長的時候,用互斥體才是較好的選擇。

8.1

當鎖鎖不能被獲取的時候,使用互斥體的開銷是程序上下文切換的時間,使用自旋鎖的開銷時間是等待獲取自旋鎖(由臨界區執行時間決定),如果臨界區較小,宜使用自旋鎖,反之宜使用互斥體

8.2

互斥體所保護的臨界區可以包含引起阻塞的**,但是自旋鎖必須要絕對避免用來保護包含可能引起阻塞的**臨界區,因為阻塞導致程序的切換,如果程序被切換出去,另乙個程序企圖獲取本自旋鎖,會導致死鎖。(還沒有釋放鎖,遞迴獲取鎖)

Linux 裝置驅動併發控制例項

在前面的筆記中,學習了linux裝置驅動中的併發控制,其中有中斷遮蔽 原子操作 自旋鎖 訊號量 互斥體及完成量。這幾種併發控制的技術就是解決多程序或多cpu之間對共享資源的同時訪問引起的競態問題。它們之間根據各自的性質使用在不同的場合中,這裡就不重複的介紹了,下面來分析 linux裝置驅動開發詳解 ...

linux裝置驅動學習(三) 併發控制

1.併發介紹 一般來說,作業系統都是支援併發執行能力的,多個執行單元訪問同乙個模組時,如果不能支援併發,則會讓這個模組功能紊亂,像讀寫操作時。兩個使用者同時讀寫,那麼可能乙個使用者執行讀操作時,另乙個使用者可以執行了它的寫操作,這就會出現功能不協調的情況。因此這裡通過併發,將 放在臨界區,通過特定的...

Linux 裝置驅動中的併發控制

是指作業系統中,乙個時間段中有幾個程式都處於啟動執行到執行完畢間,且這幾個程式都是同乙個處理器上執行,但任何乙個時間點只有乙個程式在處理機器上執行。併發容易導致競爭問題。是兩個或者多個程序同時訪問乙個資源,從而引起的資源錯誤。所謂的原子操作就是該作業系統不會在執行完畢前被任何其他任務或者事件打斷。也...