实时系统基础:硬实时与软实时、RTOS简介、任务调度策略、中断处理机制
各位同学,今天我们来聊聊实时系统。说实话,这个主题是《Reality AI 实时推理》课程的基石。你想想看,如果你的AI模型推理结果再准,但每次响应都要等上几秒钟,那在实际场景中基本就是废的。
我当年刚入行时,对“实时”的理解特别肤浅。以为实时就是“快”。后来被现实狠狠教育了一顿。有一次做工业视觉检测,模型精度99.5%,但推理延迟偶尔会抖动到200毫秒。结果呢?产线上的机械臂直接撞上了工件。嗯,那次事故让我彻底明白了——实时系统的核心不是“快”,而是“可预测”。
硬实时 vs 软实时
我们先来区分两个概念:硬实时和软实时。说白了,就是看 deadline 能不能丢。
硬实时(Hard Real-Time):错过截止时间 = 系统失败。后果可能是灾难性的。
软实时(Soft Real-Time):偶尔错过截止时间可以接受,但性能会下降。
我举个例子你就明白了。汽车的安全气囊触发系统,那就是硬实时。从碰撞传感器触发到气囊弹出,必须在几毫秒内完成。晚1毫秒,人可能就撞上方向盘了。而视频播放器呢?它是软实时。偶尔掉一帧,用户可能眨个眼就过去了,不会出人命。
在AI推理场景中,这两种情况都有。自动驾驶的刹车决策,必须是硬实时。而语音助手的回复,软实时就够了。
| 特性 | 硬实时 | 软实时 |
|---|---|---|
| 错过截止时间 | 系统失效 | 性能下降 |
| 典型场景 | 航空、医疗、自动驾驶 | 多媒体、通信、AI助手 |
| 调度策略要求 | 确定性、可证明 | 统计性保证 |
我的经验:在做AI实时推理系统设计时,我建议你先问清楚业务方:这个场景到底能不能容忍偶尔的延迟抖动?如果对方说“绝对不能”,那你就要按硬实时的标准来设计整个软件栈。
实时操作系统(RTOS)简介
好,既然要保证实时性,那普通的Linux或者Windows行不行?说实话,不太行。通用操作系统(GPOS)的设计目标是“公平”,让每个任务都有机会运行。而实时操作系统(RTOS)的设计目标是“确定性”——我知道每个任务什么时候能跑完。
RTOS和GPOS最大的区别在哪里?我总结三点:
- 调度器:RTOS使用优先级抢占式调度,高优先级任务随时可以打断低优先级任务
- 中断响应:RTOS的中断延迟是可控的、可预测的
- 资源管理:RTOS提供优先级继承、优先级天花板等机制,防止优先级反转
常见的RTOS有哪些?FreeRTOS、VxWorks、QNX、RT-Thread。我个人比较喜欢FreeRTOS,开源、轻量、社区活跃。在AI推理场景中,如果你用嵌入式设备跑模型,FreeRTOS是个不错的选择。
注意:RTOS不是万能的。它牺牲了吞吐量和功能丰富度,换来了确定性。如果你需要跑复杂的AI框架(比如PyTorch、TensorFlow),RTOS可能不太合适。这时候可以考虑在Linux上打实时补丁(PREEMPT_RT),或者用双核架构——一个核跑RTOS做实时控制,另一个核跑Linux做AI推理。
任务调度策略:RMS 与 EDF
调度策略是实时系统的灵魂。说白了,就是决定“谁先跑、跑多久”。这里我重点讲两种经典算法:RMS(速率单调调度)和EDF(最早截止时间优先)。
RMS(Rate Monotonic Scheduling)
RMS是固定优先级调度算法。它的规则很简单:周期越短的任务,优先级越高。为什么?你想想看,周期短的任务意味着它更频繁地需要CPU,给它高优先级是合理的。
RMS有一个重要的可调度性判定条件:
U = Σ (Ci / Ti) ≤ n * (2^(1/n) - 1)
其中:
U = CPU利用率
Ci = 任务i的最坏执行时间
Ti = 任务i的周期
n = 任务数量
当n趋近无穷大时,这个上限大约是69.3%。也就是说,用RMS调度,CPU利用率超过69.3%时,理论上就无法保证所有任务都能按时完成。
我在项目中遇到过一个问题:一个系统有5个周期性任务,算下来CPU利用率是75%。按照RMS理论,这已经超限了。但实际测试时,系统运行得很稳定。为什么?因为理论分析用的是最坏情况,而实际任务的平均执行时间远小于最坏情况。不过,我还是要提醒你——做硬实时系统时,必须按最坏情况来设计,不能赌运气。
EDF(Earliest Deadline First)
EDF是动态优先级调度算法。它的规则更直观:谁的截止时间最近,谁先执行。EDF理论上可以达到100%的CPU利用率,这是它比RMS强的地方。
但EDF也有缺点。我总结一下:
- 实现复杂:每次调度都要重新计算优先级,开销比RMS大
- 过载行为不稳定:当系统过载时,EDF会“多米诺骨牌效应”——一个任务超时,可能导致一连串任务都超时
- 难以预测:动态优先级让系统的行为变得不那么直观
| 特性 | RMS | EDF |
|---|---|---|
| 优先级 | 固定 | 动态 |
| CPU利用率上限 | 约69.3%(n→∞) | 100% |
| 实现复杂度 | 低 | 高 |
| 过载行为 | 可预测 | 不稳定 |
我的建议:在AI实时推理场景中,我倾向于用RMS。原因很简单——确定性更重要。EDF虽然理论上利用率更高,但它的不确定性在工业场景中很难接受。当然,如果你的系统负载很轻,CPU利用率远低于70%,那用EDF也没问题。
中断处理机制
中断是实时系统的命脉。没有中断,CPU就只能轮询,效率低得可怕。但中断处理不好,也会带来严重的延迟问题。
中断处理一般分为两个阶段:
- 上半部(Top Half):在中断上下文中执行,要求快、快、快!通常只做最必要的工作,比如清除中断标志、拷贝数据到缓冲区
- 下半部(Bottom Half):在进程上下文中执行,可以处理更复杂的逻辑,比如唤醒等待的任务、处理数据
为什么要分上下半部?因为中断上下文不能睡眠、不能持有锁、不能做复杂操作。你想想看,如果中断处理程序里调用了malloc,那系统可能就挂了。
在RTOS中,中断延迟是一个关键指标。中断延迟 = 硬件延迟 + 软件延迟。硬件延迟取决于CPU和中断控制器,软件延迟取决于操作系统。RTOS的软件延迟通常是可预测的,一般在几微秒到几十微秒之间。
我曾经踩过一个坑:在一个实时AI视觉项目中,我用了GPIO中断来触发相机采集。结果发现中断响应时间偶尔会抖动到几百微秒。排查了很久,最后发现是中断处理程序里打印了调试日志。printf操作会占用大量时间,而且可能触发其他中断。从那以后,我定了一条铁律——中断处理程序里绝对不允许有任何I/O操作。
最后,我画了一张图,把今天讲的核心内容串起来。你可以看到,实时系统的设计是一个从需求到实现的闭环。
这张图把今天的内容串起来了。从硬实时/软实时的需求出发,选择RTOS作为基础,然后根据场景选择RMS或EDF调度策略,最后通过中断处理机制来响应外部事件。每一步都有对应的关键指标来验证设计是否满足要求。
好了,实时系统的基础就讲到这里。记住一句话:实时系统的本质不是快,而是可预测。下次你设计AI推理系统时,不妨先问问自己——我的系统需要多强的实时性?然后根据答案,选择合适的调度策略和中断处理方案。