You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux内核中prepare_to_wait_event后抢占会导致wait_event_interruptible永久睡眠吗

wait_event_interruptible抢占场景安全性疑问解答

你的推论不成立,遗漏了Linux等待队列的核心使用约定和prepare_to_wait_event的实现保障,具体分析如下:

首先我们再明确核心宏的代码逻辑:

#define ___wait_event(wq_head, condition, state, exclusive, ret, cmd)        \
({                                       \
 __label__ __out;                            \
 struct wait_queue_entry __wq_entry;                 \
 long __ret = ret;   /* explicit shadow */               \
                                     \
 init_wait_entry(&__wq_entry, exclusive ? WQ_FLAG_EXCLUSIVE : 0);    \
 for (;;) {                              \
     long __int = prepare_to_wait_event(&wq_head, &__wq_entry, state);\
                                    \
    if (condition)                          \
        break;                          \
                                    \
    if (___wait_is_interruptible(state) && __int) {         \
        __ret = __int;                      \
        goto __out;                     \
    }                               \
                                    \
    cmd;                                \
}                                   \
finish_wait(&wq_head, &__wq_entry);                 \
__out:  __ret;                                  \
})

等待队列的强制使用约定

Linux内核对等待队列的使用有统一约定,所有唤醒侧的代码都必须遵守:先修改等待条件condition为真,再调用wake_up系列接口触发唤醒,这个约定是避免竞态的核心前提。

你假设的场景分析

你假设的场景不会导致进程永久挂住,逐点说明:

  • 当执行到第8行(刚进入循环还没调用prepare_to_wait_event)时另一CPU触发唤醒:
    此时当前进程还没有把自己的等待队列项加入wq_head,这次唤醒无法遍历到当前进程,属于无效唤醒。但根据使用约定,唤醒侧发唤醒前已经把condition修改为真,接下来第11行判断condition会直接命中break,不会进入后续睡眠逻辑。
  • 当执行到第10行(刚调用完prepare_to_wait_event)触发中断被切出:
    此时进程已经被加入等待队列,状态被设置为TASK_INTERRUPTIBLE,就算被切出也不会有问题:
    1. 如果唤醒侧已经修改了condition为真,进程调度回来后第11行判断条件直接break,执行finish_wait把自己移出队列,正常退出。
    2. 如果此时刚好有唤醒信号发到该等待队列,唤醒逻辑会直接把当前进程的状态重置为TASK_RUNNING,等进程调度回来要么判断条件为真退出,要么走到cmd(wait_event_interruptible场景下就是schedule())的时候,发现自身是RUNNING状态,不会实际被挂起,直接返回进入下一次循环判断条件。

不需要抢占禁用的原因

prepare_to_wait_event内部已经用自旋锁处理了等待队列修改和并发唤醒的竞态,哪怕加入队列的过程中出现并发唤醒,也不会漏掉进程状态的更新,不需要外层额外禁用抢占。

内容的提问来源于stack exchange,提问作者Changda Li

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 00:48:02