Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 核心同步機制與任務調度深度解析

編輯:Linux 教學

使用者空間的同步(mutex, semaphore, futex)建立在「線程可被搶佔」的基礎上。但核心空間的同步複雜得多:除了進程上下文的搶佔,還有硬中斷、軟中斷、NMI、多核並行等多重並發源。不理解核心任務調度與執行上下文,就無法正確選擇自旋鎖、互斥鎖、RCU、完成量、信號量、原子變數等同步原語。本文結合核心任務調度體系,深度剖析核心同步設計哲學與實戰選型。

核心並發的四大源頭

  1. 硬中斷: 異步觸發,可打斷任意核心代碼(含關中斷區段外)。中斷上下文:無法睡眠、無法存取當前進程資源、不可呼叫會睡眠的函式。
  2. 軟中斷 / Tasklet / Workqueue: 硬中斷的延遲執行機制。軟中斷 靜態註冊,同類型可多核並行;Tasklet 動態建立,同類型串行,不同類型可並行;Workqueue 在進程上下文執行(kworker 線程),可睡眠,適合耗時處理。
  3. 核心搶佔: 2.6 之後核心可搶佔,任何執行核心代碼的線程均可能被高優先級線程搶佔,產生新的並發競爭點。
  4. 多核並行 (SMP): 多核心同時執行核心代碼,真正的物理並行,對共享資料構成實質競爭。

核心任務調度層級與執行上下文

理解「誰在跑、能不能睡、能不能被打斷」是選鎖的前提:

任務類型上下文可睡眠可被搶佔典型同步原語
硬中斷處理程式中斷上下文否否(關中斷)自旋鎖 + local_irq_save/restore
軟中斷 / Tasklet中斷上下文否否自旋鎖 / 原子變數
Workqueue (kworker)進程上下文是是Mutex / Semaphore / Completion
系統呼叫 / 核心線程進程上下文是是(可搶佔核心)Mutex / Semaphore / RCU

同步原語選型全景圖

1. 自旋鎖 - 核心同步基石

  • 適用: 中斷上下文、持鎖時間極短(< 幾微秒)、不可睡眠的臨界區。
  • 變體: spin_lock_irqsave/restore(關本地中斷)、spin_lock_bh(關底半部)、raw_spinlock(不檢查搶佈/中斷,極度底層)。
  • 原則: 持鎖期間絕對不能呼叫會睡眠的函式(kmalloc(GFP_KERNEL), mutex_lock, copy_to_user, schedule() 等)。

2. 互斥鎖 - 進程上下文首選

  • 適用: 進程上下文、持鎖時間較長、需要睡眠等待資源。
  • 優勢: 支援優先級繼承(避免優先級反轉)、可被信號中斷(mutex_lock_interruptible)、除錯支援完善(CONFIG_DEBUG_MUTEXES)。
  • 禁忌: 絕不可在中斷上下文、軟中斷、Tasklet 中使用。

3. 信號量 - 計數型同步

  • 適用: 資源計數管理(如連線池大小限制)、生產者-消費者模型。
  • 注意: 核心信號量 (struct semaphore) 同樣不可在中斷上下文使用,僅限進程上下文。

4. RCU (Read-Copy-Update) - 讀多寫少的終極武器

  • 核心思想: 讀端零開銷(無鎖、無快取行反彈),寫端複製副本修改後原子替換指標,舊副本在「寬限期」結束後回收。
  • 適用: 讀頻遠大於寫頻的資料結構(路由表、檔案系統 inode、網路裝置列表)。
  • API: rcu_read_lock()/unlock()(讀端)、synchronize_rcu() / call_rcu()(寫端同步/非同步回收)。

5. 完成量 - 線程同步輕量級選擇

  • 適用: 單次事件通知(如驅動初始化完成、硬體操作完成中斷喚醒工作隊列)。
  • API: init_completion(), wait_for_completion(), complete()。

6. 原子變數與位操作 - 無鎖計數與標誌

  • atomic_t / atomic64_t: 參考計數、統計計數器。
  • 位操作: set_bit(), test_and_set_bit() 實現無鎖標誌位操作。

實戰選型決策流

  1. 在中斷上下文/軟中斷/Tasklet? → 僅能用 自旋鎖 / 原子變數 / 位操作。需關中斷用 spin_lock_irqsave。
  2. 在 Workqueue / 系統呼叫 / 核心線程? → 優先考慮 Mutex。若需等待中斷完成的事件 → Completion。
  3. 資料結構「讀多寫少」且結構指針穩定? → 評估 RCU。
  4. 簡單計數/旗標? → atomic_t / 位操作。
  5. 跨核心大量資料同步? → 考慮 Per-CPU 變數 + 定期聚合,減少鎖競爭。

經典陷阱與最佳實踐

  • 鎖順序死鎖: 全系統統一鎖獲取順序(如:父裝置鎖 → 子裝置鎖 → 隊列鎖),使用 lockdep 靜態/動態檢測。
  • 中斷安全: 共享中斷上下文與進程上下文的資料,必須用 spin_lock_irqsave 保護,否則死鎖隱患極大。
  • RCU 寬限期陷阱: synchronize_rcu() 會睡眠,不可在中斷/自旋鎖中呼叫;回調函式 call_rcu() 在軟中斷執行,同樣不可睡眠。
  • 鎖保護粒度: 盡量縮小臨界區,避免在鎖內呼叫複雜函式、複製用戶資料、分配大塊記憶體。

總結

核心同步的本質是「在正確的上下文,用正確的原語,保護正確的資料,持有最短的時間」。沒有萬能鎖,只有對上下文、調度、並發源頭的深度理解,才能在複雜的 SMP、可搶佔核心中寫出正確、高效、可維護的同步代碼。建議配合 lockdep, lockstat, ftrace 等工具,在開發測試階段徹底暴露同步缺陷。

Copyright © Windows教程網 All Rights Reserved