併發共享資料是造成不穩定的一類隱患,
而且這種錯誤一般難以跟蹤和排程
,因此必須給核心同步以高度重視.
8.1 臨界區和競爭條件
臨界區:
訪問和操作共享資料的**段.
同步:避免併發和防止競爭條件的策略.
原子操作:
確保每個事務的完整操作
,是同步一種籠統策略說法.
8.2 加鎖
鎖提供的就是這樣一種機制:
它如同一把門鎖,
門後的房間可想象成乙個臨界區
.在乙個指定的時間內
,房間裡只有乙個執行執行緒存在
,當乙個執行緒進入房間後
,它會鎖住身後的門
;當它結束對共享資料的操作後
,就會走出房間
,開啟門鎖
.如果另乙個執行緒在房門上鎖時來
,那麼它必須等待房間內的執行緒出來並開啟鎖後
,才可以進入房間
.鎖的實現是採用原子操作實現的,
而原子操作不存在競爭
.其實現與具體的體系結構密切相關
,幾乎所有的處理器都實現了
測試和設定指令,
這一指令測試整數的值
,如果其值為
0,就設定一新值
.0意味著開鎖.而
linux
根據鎖被爭用時的行為表現
,實現了不同的鎖
,這些鎖主要表現是:
被爭用時會簡單地執行忙等待或者會使當前任務睡眠直到鎖可用為止
.8.2.1 併發執行
linux核心中併發執行的原因如下:
.中斷--
中斷幾乎可以在任務時刻非同步發生
,隨時打斷當前正在執行的**;
.軟中斷和
tasklet--
核心能在任何時刻喚醒或排程軟中斷和
tasklet,
打斷當前正在執行的**;
.核心搶占
--核心中的任務可能會被另一任務搶占;
.睡眠及與使用者空間同步
--核心執行的程序可能會睡眠
,這就會喚醒排程程式
,從而導致排程乙個新的使用者程序執行;
.對稱處理器
--兩個或多個處理器可以同時執行**.
需要保護哪些資料:
如果有其他執行執行緒可以訪問這些資料,
那麼就給這些
資料加上某種形式的鎖;
如果任何其他什麼東西能看到它
,那麼就要鎖住它.記住
:要給資料而不是**加鎖.總而言之
,幾乎訪問所有核心全域性變數和共享資料都需要某種形式的同步方法.
8.3 死鎖
死鎖乙個形象的例子就是:程序1
和程序2
都要獲取鎖a和鎖
b.如果程序
1先獲取了鎖
a,程序
2獲取了鎖
b,程序
1試圖去獲取鎖
b而程序
2試圖去獲取鎖
a.那麼這兩個程序便會發生死鎖!
防止死鎖的規則如下:
.加鎖的順序是關鍵;
.防止發生飢餓
,比如說,如果
"張"不發生,"王
"有必要一定等下去嗎?
.不要重複請求同乙個鎖;
.越複雜的加鎖方案越容易造成死鎖
.
把握linux核心設計思想系列
把握linux核心設計思想 一 系統呼叫 把握linux核心設計思想 二 硬中斷及中斷處理 把握linux核心設計思想 三 下半部機制之軟中斷 把握linux核心設計思想 四 下半部機制之tasklet 把握linux核心設計思想 五 下半部機制之工作佇列及幾種機制的選擇 把握linux核心設計思想...
IOC設計原則和核心思想
控制反轉是一種設計原則,而依賴注入di是它的一種實現方式 技術描述 class a中用到了class b的物件b,一般情況下,需要在a的 中顯式的new乙個b的物件。採用依賴注入技術之後,a的 只需要定義乙個私有的b物件,不需要直接new來獲得這個物件,而是通過相關的容器控制程式來將b物件在外部ne...
LINUX核心設計與實現之除錯
核心排程主要靠經驗和對整個作業系統的把握.18.1 排程前需要準備什麼 重現bug.18.2 核心中的 bug 引發核心中的bug 的原因如下 同步 定時限制 競爭條件.18.3 printk 在終端沒有初始化之前,printk 函式是不可用的 比如在 setup arch 函式之前 不過可以用 p...