首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux 內核等待隊列機制:wait_event_interruptible 詳細解析

     編輯:關於C語言

前言

在 Linux 內核開發中,wait_event_interruptible 是實現進程休眠與喚醒的核心接口之一。本文通過源碼宏展開,深入剖析其工作原理、狀態流轉及信號處理機制。

宏定義層級解析

第一層:wait_event_interruptible


#define wait_event_interruptible(wq, condition) \
({ \
    int __ret = 0; \
    if (!(condition)) \
        __wait_event_interruptible(wq, condition, __ret); \
    __ret; \
})
  • 先檢查 condition,若為真則直接返回 0(無需休眠)。
  • 否則調用內部實現 __wait_event_interruptible,並通過 __ret 傳回錯誤碼。
  • 使用 GCC 陳述式表達式(({ ... }))使宏可作為表達式使用。

第二層:__wait_event_interruptible


#define __wait_event_interruptible(wq, condition, ret) \
do { \
    DEFINE_WAIT(__wait); \
    for (;;) { \
        prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \
        if (condition) \
            break; \
        if (!signal_pending(current)) { \
            schedule(); \
            continue; \
        } \
        ret = -ERESTARTSYS; \
        break; \
    } \
    finish_wait(&wq, &__wait); \
} while (0)

關鍵步驟詳解

  1. DEFINE_WAIT(__wait):在棧上定義一個 wait_queue_entry 結構,初始化為當前進程(current)和喚醒函數 autoremove_wake_function。
  2. prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE):
    • 將當前進程狀態設置為 TASK_INTERRUPTIBLE(可中斷睡眠)。
    • 將 __wait 加入等待隊列 wq。
  3. 條件檢查:若 condition 成立,跳出循環。
  4. 信號檢查:signal_pending(current) 檢查是否有待處理信號。
    • 無信號 → schedule() 讓出 CPU,進入睡眠。
    • 有信號 → 設置 ret = -ERESTARTSYS,跳出循環(系統調用將被中斷並返回 -ERESTARTSYS,由內核決定是否重啟)。
  5. finish_wait(&wq, &__wait):將進程狀態恢復為 TASK_RUNNING,並從等待隊列移除 __wait。

狀態流轉圖解

TASK_RUNNING
     │
     ▼ prepare_to_wait()
TASK_INTERRUPTIBLE ──schedule()──► 睡眠(等待隊列)
     │                    │
     │ condition=true     │ signal_pending()
     ▼                    ▼
  break 循環         ret=-ERESTARTSYS
     │                    │
     └───────► finish_wait() ──► TASK_RUNNING

與相關接口對比

接口睡眠狀態可被信號喚醒返回值
wait_eventTASK_UNINTERRUPTIBLE否無(void)
wait_event_interruptibleTASK_INTERRUPTIBLE是0 / -ERESTARTSYS
wait_event_timeoutTASK_UNINTERRUPTIBLE否剩餘 jiffies(0 為超時)
wait_event_interruptible_timeoutTASK_INTERRUPTIBLE是同上

使用注意事項

  • condition 必須是無副作用的表達式,因為會被多次求值。
  • 返回 -ERESTARTSYS 時,驅動程序通常應返回該錯誤碼讓系統調用層處理重啟邏輯。
  • 若需在睡眠中執行特定動作,可使用 wait_event_interruptible_exclusive 或自定義喚醒函數。

總結

wait_event_interruptible 通過「檢查條件 → 準備等待 → 睡眠調度 → 被喚醒重新檢查」的循環,實現了高效、可中斷的進程同步。理解其宏展開後的邏輯,有助於編寫正確的驅動程序並排查休眠/喚醒相關問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved