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

PREEMPT_RT下local_lock与锁组合使用的技术疑问

Linux内核锁相关疑问解答

背景说明

近期学习Linux内核锁相关内容,了解到以下关键信息:

  • 在非PREEMPT_RT内核中,代码序列:
    local_lock_irq(&local_lock);
    raw_spin_lock(&lock);
    
    完全等价于:
    raw_spin_lock_irq(&lock);
    
  • 但上述序列在PREEMPT_RT内核中会失效,原因是local_lock_irq()被映射为不关闭中断和抢占的per-CPU spinlock_t;
  • 而代码序列:
    local_lock_irq(&local_lock);
    spin_lock(&lock);
    
    在两种内核中均可正常工作。

已知PREEMPT_RT内核的实现细节:

  • local_lock_irq通过migrate_disable和per-CPU自旋锁实现,不关闭中断和抢占;
  • spin_lock基于RT_MUTEX实现;
  • IRQ以中断线程形式运行。

疑问解答

1. 第一个代码序列在PREEMPT_RT下失效,是否因执行local_lock_irq后可能被中断线程抢占?

是的,核心原因就是执行local_lock_irq后可能被中断线程抢占,进而引发死锁:

  • PREEMPT_RT下,local_lock_irq仅禁止任务迁移、保护当前CPU上的临界区,但不关闭中断,也不禁止抢占。中断以线程形式运行,优先级通常高于普通线程,因此会抢占当前持有local_lock_irq的执行流;
  • raw_spin_lock在PREEMPT_RT下仍为自旋锁,获取时会禁用抢占。若被抢占的线程已持有raw_spin_lock,中断线程若尝试获取同一个raw_spin_lock,会进入自旋等待状态;但持有锁的线程因被抢占无法继续执行释放锁,最终导致死锁,这就是序列失效的原因。

2. 第二个序列中,非PREEMPT_RT内核下spin_lock等价于raw_spin_lock,为何该序列能在两种内核中正常工作?

这是因为spin_lock在PREEMPT_RT和非PREEMPT_RT下的实现特性,结合local_lock_irq的作用,刚好适配两种场景:

  • 非PREEMPT_RT内核:spin_lock等价于raw_spin_lock,此时序列local_lock_irq(&local_lock); spin_lock(&lock);和raw_spin_lock_irq(&lock);的效果完全一致——local_lock_irq关闭本地CPU中断并防止迁移,spin_lock处理SMP并发,合起来等同于关闭中断的自旋锁,自然能正常工作;
  • PREEMPT_RT内核:
    • local_lock_irq仍保证当前CPU上无其他执行流进入临界区,同时允许抢占;
    • spin_lock基于RT_MUTEX实现,获取锁时若无法立即持有,会进入睡眠等待而非自旋。即便当前执行流被中断线程抢占,中断线程若尝试获取同一个spin_lock,会进入睡眠,不会阻塞持有锁的线程后续执行;持有锁的线程被调度回来后,能正常释放锁,中断线程也能被唤醒获取锁,不会出现死锁。
      两者配合既满足了本地CPU的临界区保护,又适配了PREEMPT_RT的抢占式设计,因此能正常工作。

内容的提问来源于stack exchange,提问作者weikang guo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 12:45:32