当前位置:首页>Linux>Linux 实时 PREEMPT_RT 系列(2):Linux 内核抢占机制与四种抢占模型深度解析

Linux 实时 PREEMPT_RT 系列(2):Linux 内核抢占机制与四种抢占模型深度解析

  • 2026-10-11 08:46:26
Linux 实时 PREEMPT_RT 系列(2):Linux 内核抢占机制与四种抢占模型深度解析

在上一篇文章中,我们建立了实时系统的核心认知,明确了标准 Linux 不具备硬实时能力的根本原因,就是内核不可抢占、延迟不可控。而 PREEMPT_RT 之所以能把 Linux 改造为实时系统,核心就是重构了内核抢占机制。

本文继续基于 Bootlin 官方文档,完整拆解用户态抢占、内核态抢占的底层原理,逐一解析 Linux 官方提供的四种抢占配置模型,对比它们的实时性、吞吐量、适用场景,理解 PREEMPT_RT 在 Linux 架构中的定位与价值。


一、抢占(Preemption)到底是什么?

抢占是操作系统强行暂停当前正在运行的任务,转而去执行更高优先级任务的能力。它是实时系统的基础——没有抢占,就没有实时性。

1. 抢占的核心意义

  • 保证高优先级任务随时可以被执行,不被低优先级任务阻塞;
  • 让系统响应速度可控、可预测;
  • 是实现低延迟、确定性的必要前提;

2. 抢占的两个层次:用户态 vs 内核态

Linux 的任务执行分为两个状态,抢占行为完全不同:

(1)用户态抢占(User Preemption)

所有标准 Linux 都默认支持用户态抢占,但是用户态抢占解决不了内核态带来的延迟。比如发生抢占的场景有:

  • 发生中断、时钟tick、更高优先级任务唤醒;
  • 从中断返回用户态时,调度器可以直接切换任务;

(2)内核态抢占(Kernel Preemption)

当任务执行系统调用、中断处理、内核线程时,运行在内核态。 标准 Linux 早期完全不支持内核抢占,导致高优先级任务必须等内核态代码执行完才能被调度,从而导致产生延迟,最终实时性失效。

因此用户态抢占解决不了实时问题,内核态抢占才是实时 Linux 的核心。

二、标准 Linux 内核不可抢占:为什么会产生延迟?

在没有开启内核抢占的情况下,执行流程如下:

  1. 任务A 进入系统调用,运行在内核态;
  2. 硬件中断触发,中断处理程序唤醒了更高优先级的任务B;
  3. 中断返回,但因为还在内核态,调度器不能执行抢占;
  4. 必须等任务A 的系统调用完全返回用户态,任务B 才能运行;

这就造成:

  • 延迟时间 = 不可预测的内核代码执行时间;
  • 即 Unbounded Latency(无界延迟);
  • 实时系统绝对不能接受;

这就是标准 Linux 不能做硬实时的最核心原因。

三、Linux 四大抢占模型完整解析

Linux 内核提供 4 种编译级抢占配置,对应不同的实时性与吞吐量。 它们由内核配置 CONFIG_PREEMPT_* 控制,是构建实时 Linux 的第一步。

模型1:CONFIG_PREEMPT_NONE —— 无强制抢占(服务器模式)

  • 内核完全不抢占
  • 只有当内核代码主动返回、阻塞、调用 cond_resched() 时才会调度
  • 中断处理完直接返回原内核上下文

优点有:1)吞吐量最高;2)进程切换最少,缓存命中率最高;3)适合计算密集型服务器、超算、大数据场景;

缺点为:1)延迟最大、不可预测;2)完全不适合实时场景。

典型使用场景为:1)标准服务器 Linux(CentOS、RHEL Server 等);2)追求极致吞吐,不关心响应延迟;

模型2:CONFIG_PREEMPT_VOLUNTARY —— 自愿抢占(桌面模式)

  • 内核不会被“强行抢占”,但在代码中插入主动调度点
  • 内核在可能阻塞的位置调用 might_sleep(),主动让出CPU
  • 比 PREEMPT_NONE 响应更快,但仍不是完全抢占

优点为:1)吞吐量损失很小;2)桌面交互更流畅;

缺点为:1)仍存在较大延迟波动;2)不满足工业实时要求;

典型使用场景为:1)传统桌面 Linux(Ubuntu Desktop 等);2)对交互敏感,但无严格实时需求

模型3:CONFIG_PREEMPT —— 低延迟桌面抢占(嵌入式基础)

  • 内核大部分代码可抢占
  • 除了持有自旋锁 spinlock 的临界区
  • 中断返回内核态时可触发抢占

优点为:1)延迟明显降低,达到毫秒级稳定;2)适合简单嵌入式、网关、消费电子;

缺点为:1)自旋锁区域仍然不可抢占;2)临界区大的驱动会造成延迟尖峰;3)无法满足微秒级硬实时;

典型使用场景为:1)普通嵌入式 Linux;2)对延迟有要求,但非严苛实时场景。

模型4:CONFIG_PREEMPT_RT —— 完全可抢占内核(实时模式)

  • 几乎整个内核全部可抢占
  • spinlock 转为睡眠锁,不再关闭抢占
  • 中断全部线程化,可被调度、可设优先级
  • 只有极少的 raw_spinlock 临界区保持原子性

优点为:1)内核延迟可预测、有界;2)实时任务几乎不会被阻塞;3)满足工业控制、车载、机器人等硬实时需求;

缺点为:1)吞吐量略有下降;2)部分驱动、内核模块需要适配;3)对硬件有一定要求;

典型使用为:1)工业自动化、运动控制;2)智能驾驶、车载平台;3)机器人、医疗设备;4)低延迟通信、音视频实时处理;

四种抢占模型核心对比

配置项
抢占能力
内核抢占
自旋锁影响
延迟
吞吐量
适用场景
PREEMPT_NONE
无
否
不抢占
最大、不可控
最高
服务器、超算
PREEMPT_VOLUNTARY
弱
主动让出
不抢占
较大
高
桌面系统
PREEMPT
中
大部分可抢
锁区不抢占
中等、可控
中
嵌入式、普通低延迟
PREEMPT_RT
最强
几乎全部可抢
锁变为睡眠锁
最低、最稳定
略低
工业/车载/硬实时

因此PREEMPT_RT 是唯一能让 Linux 具备真正实时能力的抢占模型。

四、PREEMPT_RT 实现“完全内核抢占”的方式

标准 Linux 无法抢占,是因为以下三点原因:

  1. 自旋锁会关闭抢占;
  2. 中断处理关闭中断;
  3. 临界区不可被打断;

PREEMPT_RT 从底层机制对以往的实现进行了改造,分别如下:

1. 自旋锁修改为实时睡眠锁

  • 普通 spinlock_t / rwlock_t 变为可睡眠的 rt_mutex;
  • 加锁不再关闭抢占;
  • 支持优先级继承,解决优先级反转;

2. 中断线程化

  • 绝大多数硬件中断转为内核线程;
  • 中断处理可以被抢占、设优先级、被调度;
  • 避免中断长时间阻塞实时任务;

3. 保留极小范围原子区

  • 只有真正必须保护的硬件操作使用 raw_spinlock_t;
  • 临界区极小,延迟完全可控;

4. 高分辨率定时器

  • 脱离系统tick,支持微秒级定时;
  • 让任务唤醒更精准;

通过这四点,PREEMPT_RT 实现了 Linux 历史上最强的内核抢占能力。

抢占模型对实时延迟的真实影响

在相同硬件下,四种模型的最坏延迟大致如下(仅供参考,实际延迟值还需要结合具体运行的硬件平台):

  • PREEMPT_NONE:几十~几百毫秒;
  • PREEMPT_VOLUNTARY:十几~几十毫秒;
  • PREEMPT:几毫秒;
  • PREEMPT_RT:几十~几百微秒;

这就是为什么工业控制、机器人、自动驾驶必须使用 PREEMPT_RT。


五、总结

  1. 实时性的核心是内核抢占,不是用户态抢占;
  2. 标准 Linux 内核不可抢占 → 无界延迟 → 不具备硬实时能力;
  3. Linux 提供 4 种抢占模型,从无抢占到完全抢占逐级增强;
  4. PREEMPT_RT 是唯一真正的实时抢占模型
    ,实现全内核可抢占;
  5. PREEMPT_RT 通过锁重构、中断线程化、优先级继承,实现确定性低延迟;
  6. 抢占模型选择:吞吐选NONE,交互选VOLUNTARY,嵌入式选PREEMPT,实时必选RT。

最新文章

随机文章