一.概念
1.併發(concurrency)指多個執行單元同時,並行被執行。
2.併發的執行單元對共享資源,(比如說,硬體資源,全域性變數,靜態變數等)訪問很容易導致競態(race conditions)。
舉個簡單事例,古代皇帝有很多妃子,皇帝第乙個時辰是宜妃的,第二個時辰是萱妃,最後時間是皇后的,這是原來正常的順序。假如宜妃讓皇帝賴床了,萱妃不爽了,然後萱妃時間衝突了,皇后也不爽了,競爭就產生了,然後就是一部血雨腥風的後宮大戲。(呃,清宮劇,廣告太厲害了,連我不看的都影響了)在linux中我們不需要這種大戲。
3.造成競態的主要原因:
1.對稱多處理器(smp)4.解決方案多個cpu使用共同的系統匯流排,訪問共同的外設和儲存器。
2.單cpu內程序與搶占它的程序
高優先順序搶占低優先順序
3.中斷與程序之間
4.中斷與中斷之間
保證對共享資源的互斥訪問。
訪問共享資源的**區域稱為臨界區。
方法:中斷遮蔽,原子操作,自旋鎖,訊號量等
二.用法
1.中斷遮蔽
單cpu範圍內避免競態的一種簡單而省事的方法
一旦中斷遮蔽,程序排程不會發生,中斷和程序之間的併發不會發生
缺點:很多硬體事件不能得到及時處理,可能造成資料丟失,系統崩潰。
為什麼呢,因為linux的非同步i/o,程序排程等都依賴於中斷,在遮蔽中斷期間所有的中斷都無法得到處理。
注意:單獨使用中斷遮蔽不是乙個好方法,宜與自旋鎖聯合使用
用例
local_irq_disable();2.原子操作...臨界區...
local_irq_enable();
在執行過程中不會被別的**路徑所中斷的操作
函式分兩類,分別針對 位和整型變數
用例:
static atomic_t *** = atomic_init(1); //定義原子變數並初始化為13.自旋鎖if(!atomic_dec_and_test(&***)) // atomic_dec_and_test 測試減一是否為零,為零返回true
atomic_inc(&***);
return -ebusy;
atomic_inc(&***); //釋放裝置
自旋鎖有「加鎖」和「解鎖」兩種狀態。
我的理解是,「加鎖」一直在尋求「解鎖」,「解鎖」馬上會尋求「加鎖」,並原地打轉,所以加鎖位置的**進入臨界區執行,直到解鎖。
注意:1.占用臨界區的時間必須短;
2.擁有自旋鎖期間所在的cpu程序搶占被關閉
3.占有自旋鎖期間不能呼叫引起阻塞的函式(原子上下文)比如:copy_from_user(), kmalloc(), msleep()
4.自旋鎖可以被用於中斷上下文
特殊化自旋鎖:讀寫自旋鎖,順序鎖,rcu鎖
用例:
spinlock_t lock; //定義自旋鎖4.訊號量spin_lock_init(&lock); //初始化自旋鎖
spin_lock(&lock); // 獲取自旋鎖
...臨界區...
spin_unlock(&lock)
與自旋鎖類似,不同的是,當獲取不到訊號量時,程序不會原地打轉而是進入休眠等待狀態。
注意:1.訊號量是程序級的,當程序占用資源時間較長時,訊號量是較好的選擇(因為程序上下文切換的開銷很大)
2.臨界區可以包含可能引起阻塞的**,可以進入休眠
3.訊號量不能被用於中斷上下文
用例
declare_mutex(***_sem); //定義乙個 訊號量並初始化為1down(&***_sem); //獲取訊號量
...臨界區...
up(&***_sem); //釋放訊號量
Linux併發控制
目錄 併發和競態 編譯亂序和執行亂序 中斷遮蔽 原子操作 位原子操作 自旋鎖訊號量 互斥體完成量 1.併發是多個執行單元同時並行的執行。2.競態是指併發操作對共享資源的訪問。競態的發生情況如下 1.對稱多處理器 smp 的多個cpu的程序 中斷之間的併發為核間併發。2.單個cpu內的多個程序併發訪問...
linux併發控制例子
例項篇 1.定義帶有裝置併發控制方案的結構體 諸如訊號量,自旋鎖等,反正前邊那麼多了 我是一名高手,告訴大家乙個高手的習慣,就是喜歡也習慣把將某裝置所使用的自旋鎖,訊號量等輔助手段也放到裝置結構體中,就像下邊這樣 struct csyncontrol dev 然後,將訊號量的初始化工作放到模組初始化...
linux 併發控制總結
atomic t atomic t atom atomic init 1 atomic dec and test atom atomic inc atom spin lock t spinlock t lock spin lock init lock define spinlock lock spi...