我們已展現的喚醒進程的樣子比內核中真正發生的要簡單. 當進程被喚醒時產生的真正動 作是被位於等待隊列入口項的一個函數控制的. 缺省的喚醒函數[22]22設置進程為可運行的 狀態, 並且可能地進行一個上下文切換到有更高優先級進程. 設備驅動應當從不需要提供 一個不同的喚醒函數; 如果你例外, 關於如何做的信息見 <linux/wait.h>
我們尚未看到所有的 wake_up 變體. 大部分驅動編寫者從不需要其他的, 但是, 為完整 起見, 這里是整個集合:
wake_up(wait_queue_head_t *queue); wake_up_interruptible(wait_queue_head_t *queue);
wake_up 喚醒隊列中的每個不是在互斥等待中的進程, 並且就只一個互斥等待者, 如果它存在. wake_up_interruptible 同樣, 除了它跳過處於不可中斷睡眠的進程. 這些函數, 在返回之前, 使一個或多個進程被喚醒來被調度(盡管如果它們被從一 個原子上下文調用, 這就不會發生).
wake_up_nr(wait_queue_head_t *queue, int nr); wake_up_interruptible_nr(wait_queue_head_t *queue, int nr);
這些函數類似 wake_up, 除了它們能夠喚醒多達 nr 個互斥等待者, 而不只是一個. 注意傳遞 0 被解釋為請求所有的互斥等待者都被喚醒, 而不是一個沒有.
wake_up_all(wait_queue_head_t *queue); wake_up_interruptible_all(wait_queue_head_t *queue);
這種 wake_up 喚醒所有的進程, 不管它們是否進行互斥等待(盡管可中斷的類型仍 然跳過在做不可中斷等待的進程)
wake_up_interruptible_sync(wait_queue_head_t *queue);
正常地, 一個被喚醒的進程可能搶占當前進程, 並且在 wake_up 返回之前被調度 到處理器. 換句話說, 調用 wake_up 可能不是原子的. 如果調用 wake_up 的進程 運行在原子上下文(它可能持有一個自旋鎖, 例如, 或者是一個中斷處理), 這個重 調度不會發生. 正常地, 那個保護是足夠的. 但是, 如果你需要明確要求不要被調 度出處理器在那時, 你可以使用 wake_up_interruptible 的"同步"變體. 這個函 數最常用在當調用者要無論如何重新調度, 並且它會更有效的來首先簡單地完成剩 下的任何小的工作.
如果上面的全部內容在第一次閱讀時沒有完全清楚, 不必擔心. 很少請求會需要調用 wake_up_interruptible 之外的.