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

Linux内核:访问per-CPU变量时为何禁用抢占?

关于get_cpu_var()宏禁用抢占的原因及内核抢占的说明

首先咱们先拆解下你提到的这个宏:

#define get_cpu_var(var) \
    (*({ \
        preempt_disable(); \
        this_cpu_ptr(&var); \
    }))

它的核心作用是安全获取当前CPU对应的per-CPU变量实例,接下来逐个解答你的问题:

1. 为什么要在此处禁用抢占?

per-CPU变量的本质是每个CPU拥有独立的变量副本,目的是减少锁竞争、提升性能。但这里有个关键前提:你拿到的指针绑定的是当前CPU的副本。

如果不禁用抢占,会出现致命问题:假设进程A在CPU0上调用get_cpu_var()拿到了CPU0上的var副本指针,紧接着还没完成对这个变量的操作,就被调度器抢占,切换到了CPU1上运行。这时候进程A如果继续使用之前拿到的指针,访问的还是CPU0的副本,而不是当前所在CPU1的副本——这完全违背了per-CPU变量的设计初衷,会导致数据错误或者不一致。

所以preempt_disable()的作用是锁住当前CPU绑定关系:从获取per-CPU变量指针开始,直到你调用put_cpu_var()(对应解锁抢占)这段时间,当前进程不会被调度到其他CPU,确保你访问的始终是当前CPU的正确副本。

2. 内核环境中难道不会发生抢占吗?

当然会!现代Linux内核默认支持抢占式内核(通过CONFIG_PREEMPT系列配置开启),内核空间的代码并非完全不可抢占:

  • 在进程上下文(比如系统调用执行过程、内核线程运行时),只要当前代码没有持有自旋锁、没有处于中断上下文,调度器就可以抢占当前进程,让更高优先级的进程运行。
  • 只有在一些特殊场景下内核才不会被抢占:比如持有自旋锁时、中断上下文执行时、调用了preempt_disable()的代码段内。

简单说,内核本身是执行抢占操作的主体,但这并不意味着内核代码永远不会被抢占——恰恰相反,抢占式内核的设计就是为了提升系统响应性,让高优先级任务能更快得到执行。

内容的提问来源于stack exchange,提问作者tomer.z

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:44:25