- 中斷和中斷處理.
- 中斷: 由于處理器和外設(shè)速度上的差異, 在兩者協(xié)同工作時, 讓硬件在需要時再向內(nèi)核發(fā)出信號.
- 特殊的電信號, 處理器接收到后, 交予OS來處理.
- 隨時可以發(fā)生.
- 特定的中斷與特定的設(shè)備相關(guān)聯(lián), 且內(nèi)核知道這些信息.
- 異常是同步中斷, 產(chǎn)生時必須考慮與CPU 時鐘同步.
- 中斷處理程序.
- 特定的類型聲明的C函數(shù).
- 上半部與下半部. 既要快速運行,又要完成盡可能多的工作量
- 上半部: 在所有中斷被禁止時, 只做嚴格優(yōu)先的工作.
- 下半部: 能被允許稍后完成的工作.
- 使用中斷的設(shè)備, 其相應(yīng)的驅(qū)動程序需要注冊中斷處理程序.
- 當(dāng)一個中斷處理程序在執(zhí)行時,相應(yīng)的中斷線在所有處理器上都被屏蔽掉. 所以不會重入.
- 中斷上下文.
- 由于沒有后備進程, 所以不可以睡眠, 同時也不能調(diào)用可能睡眠的函數(shù).
- 中斷: 由于處理器和外設(shè)速度上的差異, 在兩者協(xié)同工作時, 讓硬件在需要時再向內(nèi)核發(fā)出信號.
- 內(nèi)核同步方法
- 原子操作.
- 兩個原子操作不可能并發(fā)地訪問同一變量.
- 自旋鎖.
- 在短時間內(nèi)進行輕量級加鎖.
- 線程在等待它重新可用時自旋, 這點特別浪費CPU時間, 所以自旋鎖不應(yīng)該被長時間持有.
- 需要禁止本地中斷, 來防止中斷自旋.
- 鎖的是數(shù)據(jù)而不是代碼, 保護的是臨界區(qū)中的數(shù)據(jù).
- 讀寫自旋鎖
- 對數(shù)據(jù)的操作可以劃分為讀/寫或消費者/生產(chǎn)者類別時.
-
不能把讀鎖升級為寫鎖.
- 語句:
read_lock; write_lock.
- 會導(dǎo)致死鎖: 寫鎖不斷自旋,等到讀鎖被釋放,包括自己.
- 當(dāng)需要寫操作時, 要在一開始就直接申請寫鎖.
- 語句:
- 即使一個線程遞歸地獲得同一讀鎖也是安全的.
- 照顧讀的鎖.
- 當(dāng)讀鎖被持有時, 寫操作為了互斥只能等待.
- 多個讀者很容易造成寫者饑餓.
- 信號量.
- 睡眠鎖, 會導(dǎo)致兩次上下文切換.
- 由于可能會睡眠, 需要維護等待隊列以及喚醒的開銷. 它只適合于鎖會被長時間持有的情況.
- 持有信號量時可以睡眠, 而自旋鎖是不允許睡眠的.
- 由于鎖被爭用時會睡眠, 所以只能在進程上下文中獲取信號量. 因為在中斷上下文種不能進行調(diào)度.
- 持有信號量的代碼可以被搶占.
- 信號量可以同時允許任意數(shù)量的鎖持有者.
- 互斥信號量(只允許一個持有者), 計數(shù)信號量(>1).
- 兩個原子操作 P,V. down/up.
- 讀寫信號量. 都是互斥信號量. 只對寫者互斥.
-
downgrade_write
: 將寫鎖降級為讀鎖.
-
- 互斥體.
- mutex. 更簡單的睡眠鎖.
- 更多的限制: 在同一上下文上鎖和解鎖. 不允許遞歸地上鎖和解鎖. 當(dāng)持有一個mutex時,進程不能退出.
- 首選互斥體, 當(dāng)不滿足其某個限制時, 再選擇信號量.
- 中斷上下文中只能使用自旋鎖, 而在任務(wù)睡眠時只能使用互斥體.
- 完成變量.
- 簡單的信號量的替代.
- 過程:
wait_for_completion + complete
- 順序鎖.
- 用于讀寫共享數(shù)據(jù), 如序列計數(shù)器.
- 鎖的初值為0, 寫鎖使值變?yōu)槠鏀?shù), 釋放時變?yōu)榕紨?shù).
- 在讀取數(shù)據(jù)的前后, 序列號都會被讀取, 若相同, 則說明讀沒有被寫打斷過, 或者讀取值為偶數(shù)時, 也沒有發(fā)生過寫操作.
- 對寫者更有利: 只要沒有寫者, 就能獲得寫鎖.
- 禁止搶占.
- 如果一個自旋鎖被持有, 內(nèi)核便不能進行搶占. 這是為了保持內(nèi)核的搶占安全.
- 搶占計數(shù)器 = 被持有鎖的數(shù)量(preempt_enable的次數(shù)) - preempt_disable的調(diào)用次數(shù).
- 順序和屏障.
- CPU為了優(yōu)化其傳輸管道,打亂了分配和提交指令的順序.
- 屏障: 指示編譯器不要對給定點周圍的指令序列進行重新排序.
- 原子操作.