PREEMPT_RT 技术实现:Sleeping spinlocks

📅 2026/7/2 2:58:49
PREEMPT_RT 技术实现:Sleeping spinlocks
拿不到锁时不阻塞休眠、不放弃 CPU在原地循环忙等自旋一直轮询直到锁被释放适合持有时间极短的场景工作原理线程尝试spin_lock()加锁锁空闲 → 立刻拿到锁进入临界区锁被别人拿着 →原地循环自旋不断查锁状态持有者spin_unlock()释放锁自旋的线程立刻抢到锁继续执行和 Mutex 区别Mutex拿不到就睡眠阻塞让出 CPUSpinlock拿不到原地自旋忙等占着 CPU 不放适用场景 优缺点优点开销极低无进程调度、无睡眠/唤醒开销实现简单适合短临界区锁持有时间 一次进程切换耗时比 mutex 更快缺点忙等浪费 CPU长时间拿不到锁CPU 空转浪费算力可能造成实时延迟持有者不释放其他 CPU 一直自旋不能在持有锁时睡眠一旦睡眠所有人永久自旋死锁适用场景临界区执行时间非常短中断上下文不能睡眠不能用 mutex多核间简单同步不允许进程调度的场景不适用场景临界区逻辑复杂、耗时久可能触发睡眠、调度、内存分配等操作PREEMPT_RT 实时内核下的Spinlock特征在非PREEMPT_RT标准Linux内核抢占模型中自旋锁直接映射为原始自旋锁raw spinlock。一个等待自旋锁的任务会持续自旋忙等直到持有锁的任务释放它原始自旋锁上下文会禁用抢占。在PREEMPT_RT实时内核中普通自旋锁被映射为rt_mutex_base实时互斥锁成为睡眠式自旋锁Sleeping Spinlocks而原始自旋锁raw spinlock保留原有行为。等待睡眠式自旋锁的任务会主动睡眠锁被释放时才会被唤醒睡眠式自旋锁上下文不会禁用抢占。代码实现从下面的代码实现。不难看出在preempt_rt kernel中rt_mutex_base代替raw_spinlock成为spinlock的底层实现。而rt_mutex_base则是我在文章PREEMPT_RT 技术实现rt_mutex中介绍过的rt_mutex。//code path:include/linux/spinlock_type.h #ifndef CONFIG_PREEMPT_RT /* Non PREEMPT_RT kernels map spinlock to raw_spinlock */ typedef struct spinlock { union { struct raw_spinlock rlock; ... #else /* !CONFIG_PREEMPT_RT */ /* PREEMPT_RT kernels map spinlock to rt_mutex */ #include linux/rtmutex.h typedef struct spinlock { struct rt_mutex_base lock; ...