实时 Linux

一、什么是实时

二、Linux 实时性挑战

三、内核抢占模型

# /proc/config.gz
CONFIG_PREEMPT_NONE=y        # 不可抢占(吞吐最高)
CONFIG_PREEMPT_VOLUNTARY=y   # 自愿点
CONFIG_PREEMPT=y             # 抢占式(桌面)
CONFIG_PREEMPT_RT=y          # 完全可抢占(实时)
模型 调度延迟 吞吐
NONE 数十 ms 最高
VOLUNTARY ~5 ms
PREEMPT ~1 ms
PREEMPT_RT < 100us 中低

四、PREEMPT_RT

1. 概念

2. 获取

3. 验证延迟

# cyclictest
git clone https://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git
cd rt-tests && make
./cyclictest -l 1000000 -m -smp -p 90 -i 1000 -h 200 -q | tail -100

# 看最高延迟
cat /sys/kernel/debug/sched/debug

4. 实时线程

#include <sched.h>
#include <pthread.h>

struct sched_param sp = { .sched_priority = 80 };
pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp);

// 内存锁
mlockall(MCL_CURRENT|MCL_FUTURE);

// 注意:实时任务不能调用 malloc、printf 等

五、Xenomai(双内核)

1. 架构

2. 优势

3. 安装

4. 编程

#include <alchemy/task.h>
RT_TASK mytask;
rt_task_create(&mytask, "mytask", 0, 80, T_JOINABLE);
rt_task_start(&mytask, &mytask_func, NULL);

void mytask_func(void *arg) {
    rt_task_set_periodic(NULL, TM_NOW, 1000000);  // 1ms 周期
    while (1) {
        rt_task_wait_period(NULL);
        // 实时业务
    }
}

六、其他方案

1. PREEMPT_RT 替代品

2. 实时 OS 与 Linux 协作

3. 商业方案

七、调优技巧

1. 隔离 CPU

# 启动参数
isolcpus=2,3                # CPU2,3 不参与调度
nohz_full=2,3 rcu_nocbs=2,3 # 减少 tick 和 RCU

2. 绑核

cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(2, &set);
pthread_setaffinity_np(pthread_self(), sizeof(set), &set);

3. 优先级

# 进程优先级
chrt -f -p 90 PID
chrt -r -p 50 PID

# 看 CPU 占用与调度延迟
top -H
htop

4. 中断线程化

八、测量工具

# cyclictest
cyclictest -l 100000 -m -S -p 80 -i 1000 -h 200

# stress-ng
stress-ng --vm 1 --timeout 60s

# 实际场景测试
- 控制循环响应时间
- 中断→用户态→输出 延迟

# OSADL 实时质量评估
https://www.osadl.org/Quality-of-Service.html

九、嵌入式实时注意

十、典型实时应用

场景 方案
工业 PLC PREEMPT_RT + Xenomai
机器人 PREEMPT_RT + ROS 2
医疗设备 PREEMPT_RT
视频处理 Xenomai + 多核分工
运动控制 Xenomai(最低延迟)