1. RTOS 基础概念:实时操作系统定义、任务、调度器、内核对象概述
1.1 实时操作系统(RTOS)定义
实时操作系统(Real-Time Operating System, RTOS)是一种专门为满足严格时间约束而设计的系统软件。与通用操作系统(如 Linux、Windows)追求“平均吞吐量”不同,RTOS 的核心目标是保证任务在规定的截止时间(Deadline)内完成,即可预测性与确定性。
关键区分: 硬实时系统(错过截止时间 = 系统失效,如汽车安全气囊) vs. 软实时系统(错过截止时间 = 性能下降,如视频播放)。
| 特性 | 通用操作系统(GPOS) | 实时操作系统(RTOS) |
|---|---|---|
| 调度目标 | 公平性、高吞吐量 | 确定性、低延迟、满足截止时间 |
| 内核抢占 | 通常可抢占,但中断关闭时间较长 | 完全可抢占,中断响应时间极短 |
| 任务优先级 | 动态优先级(时间片轮转) | 静态/动态优先级,支持优先级继承 |
| 典型应用 | 桌面、服务器、移动设备 | 工业控制、汽车电子、航空航天、IoT |
1.2 任务(Task)
任务是 RTOS 中独立调度和执行的代码单元,通常是一个无限循环的 C 函数。每个任务拥有独立的栈空间和任务控制块(TCB),用于保存上下文和状态信息。
任务状态机是理解 RTOS 行为的基础。一个任务在其生命周期中会在以下状态间转换:
- 就绪(Ready): 任务已具备运行条件,等待调度器分配 CPU。
- 运行(Running): 任务正在占用 CPU 执行。
- 阻塞(Blocked): 任务因等待某个事件(如信号量、队列消息、延时)而暂停执行。
- 挂起(Suspended): 任务被显式暂停,不参与调度,直到被恢复。
嵌入式开发避坑: 初学者常犯的错误是在任务中编写
while(1) 空循环或使用 delay() 忙等待,这会浪费 CPU 周期并阻塞低优先级任务。正确的做法是使用 RTOS 提供的阻塞 API(如 vTaskDelay() 或等待信号量)。
1.3 调度器(Scheduler)
调度器是 RTOS 内核的核心组件,负责决定下一个要运行的任务。调度策略直接决定了系统的实时性能。常见的调度算法包括:
- 优先级抢占式调度(Preemptive Priority Scheduling): 每个任务被赋予一个优先级,调度器始终运行当前就绪态中优先级最高的任务。高优先级任务可以抢占正在运行的低优先级任务。这是大多数商业 RTOS(如 FreeRTOS、uC/OS-III)的默认策略。
- 时间片轮转调度(Round-Robin): 相同优先级的任务轮流获得固定长度的时间片,适用于非实时或软实时场景。
- 单调速率调度(Rate Monotonic Scheduling, RMS): 静态优先级调度,周期越短的任务优先级越高,是理论上的最优静态优先级调度算法。
- 最早截止时间优先(Earliest Deadline First, EDF): 动态优先级调度,截止时间越早的任务优先级越高,理论上最优但实现复杂。
优先级反转陷阱: 在优先级抢占式调度中,如果低优先级任务持有高优先级任务需要的共享资源,高优先级任务会被迫等待,导致优先级反转。这是 RTOS 中最经典的缺陷之一,将在后续章节深入分析。
1.4 内核对象(Kernel Objects)概述
内核对象是 RTOS 提供的用于任务间通信、同步和资源共享的机制。它们是构建复杂嵌入式应用的基础构件。
| 内核对象 | 核心用途 | 典型 API(以 FreeRTOS 为例) |
|---|---|---|
| 信号量(Semaphore) | 资源计数、任务同步(二值/计数) | xSemaphoreCreateBinary(), xSemaphoreGive(), xSemaphoreTake() |
| 互斥量(Mutex) | 保护共享资源,内置优先级继承 | xSemaphoreCreateMutex() |
| 消息队列(Queue) | 任务间传递数据(FIFO) | xQueueCreate(), xQueueSend(), xQueueReceive() |
| 事件组(Event Group) | 多事件同步(与/或逻辑) | xEventGroupCreate(), xEventGroupSetBits() |
| 任务通知(Task Notification) | 轻量级信号量/消息,直接发给任务 | xTaskNotifyGive(), ulTaskNotifyTake() |
| 软件定时器(Software Timer) | 周期性或一次性回调 | xTimerCreate(), xTimerStart() |