0.2 RTOS 基础概念
2026/7/19大约 4 分钟预备知识预备知识RTOS任务调度
0.2 RTOS 基础概念
📚 本节导读
学习时长:约 20 分钟
难度级别:⭐⭐☆☆☆
前置知识:第 0.1 节嵌入式系统基础
🎯 学习目标
- 理解 RTOS 与裸机编程的区别
- 掌握任务、调度、优先级、上下文切换等核心概念
- 了解常见的 IPC 机制(信号量、互斥锁、消息队列)
- 理解 RTOS 中的中断处理
一、裸机 vs RTOS
1.1 裸机编程(Super Loop)
/* 裸机:无限循环轮询 */
int main(void)
{
while (1) {
task1(); // 读取传感器
task2(); // 更新显示
task3(); // 处理通信
// 问题:task1 耗时过长会阻塞 task2 和 task3
}
}痛点:一个任务阻塞,其他任务全部停止。
1.2 RTOS 编程(多任务)
/* RTOS:多个任务并发执行 */
void task1(void *arg) {
while (1) { read_sensor(); os_task_msleep(100); }
}
void task2(void *arg) {
while (1) { update_display(); os_task_msleep(50); }
}
void task3(void *arg) {
while (1) { handle_comm(); os_task_msleep(200); }
}
int main(void) {
os_task_create(..., task1, ...); // 创建任务1
os_task_create(..., task2, ...); // 创建任务2
os_task_create(..., task3, ...); // 创建任务3
os_kernel_start(); // 启动调度
}优势:调度器自动切换任务,一个任务阻塞不影响其他任务。
二、核心概念
2.1 任务(Task / Thread)
任务是 RTOS 中独立运行的执行单元,每个任务有自己的:
- 栈空间(Stack):存储局部变量和函数调用上下文
- 优先级(Priority):决定被调度的顺序
- 任务控制块(TCB):存储任务状态信息
┌─────────────────────────────────────┐
│ 任务调度 │
│ │
│ Task1 (高优先级) ──► 运行 ──► 休眠 │
│ Task2 (中优先级) ──► 就绪 ──► 运行 │
│ Task3 (低优先级) ──► 就绪 ──► 就绪 │
│ │
│ 时间 ──────────────────────────────►│
└─────────────────────────────────────┘2.2 任务状态
┌──────────┐
│ 就绪态 │ ← 任务等待 CPU
│ (Ready) │
└────┬─────┘
│ 调度器选中
▼
┌──────────┐
│ 运行态 │ ← 当前占用 CPU 的任务
│ (Running)│
└────┬─────┘
│ 等待事件/延时/阻塞
▼
┌──────────┐
│ 阻塞态 │ ← 等待信号量/延时中
│ (Blocked)│
└────┬─────┘
│ 事件到达/超时
▼
┌──────────┐
│ 就绪态 │
└──────────┘2.3 调度器(Scheduler)
调度器决定哪个任务获得 CPU 使用权。OneOS 使用抢占式优先级调度:
- 高优先级任务就绪时,立即抢占低优先级任务
- 同优先级任务按时间片轮转
2.4 上下文切换(Context Switch)
从一个任务切换到另一个任务时,CPU 需要:
- 保存当前任务的状态(寄存器、栈指针、PC)
- 恢复下一个任务的状态
- 跳转到下一个任务的执行位置
这是 RTOS 的核心开销,切换越频繁,CPU 有效利用率越低。
2.5 优先级
- 数值越小,优先级越高(OneOS 中 0 为最高优先级)
- 优先级数量可配置(如
OS_TASK_PRIORITY_MAX = 32) - 空闲任务(Idle Task)始终为最低优先级
三、IPC 机制(任务间通信)
3.1 信号量(Semaphore)
用于任务同步和资源计数:
Task1: 需要资源 Task2: 释放资源
│ │
├─ os_sem_wait(sem) ──► │ (sem 不足,阻塞)
│ │
│ ◄── os_sem_post(sem)
│ │ (sem+1,唤醒 Task1)
├─ 继续执行 │3.2 互斥锁(Mutex)
保护共享资源,防止多个任务同时访问:
Task1: Task2:
mutex_lock(); mutex_lock(); // 阻塞等待
write_to_flash(); // 等待...
mutex_unlock(); mutex_lock(); // 获得锁
write_to_flash();
mutex_unlock();3.3 消息队列(Message Queue)
任务间传递数据:
Task1: 发送消息 Task2: 接收消息
│ │
├─ os_mq_send(mq, &msg) ──► │
│ ├─ os_mq_recv(mq, &msg)
│ │ (收到消息)3.4 各机制对比
| 机制 | 用途 | 关键特征 |
|---|---|---|
| 信号量 | 同步、资源计数 | 计数器,无数据传递 |
| 互斥锁 | 互斥访问 | 二值,有优先级继承 |
| 事件 | 多条件触发 | 32 位标志位,可"与/或"等待 |
| 消息队列 | 数据传递 | FIFO,可存放多条消息 |
| 邮箱 | 数据传递 | 单条消息,效率高 |
四、RTOS 中的中断
4.1 中断处理原则
- ISR 应尽可能短:在 ISR 中只做必要操作(如释放信号量),耗时处理放到任务中
- ISR 不阻塞:ISR 中不能调用可能阻塞的 API(如
os_sem_wait) - 使用 FromISR 版本 API:如
os_sem_post_from_isr()
4.2 典型模式
中断触发
│
├─ ISR: 读取数据,os_sem_post_from_isr()
│
└─ Task: os_sem_wait() → 处理数据📝 本节小结
- RTOS 通过多任务并发解决了裸机轮询的阻塞问题
- 核心概念:任务 → 状态机 → 调度器 → 上下文切换 → 优先级
- IPC 机制:信号量(同步)、互斥锁(互斥)、消息队列(数据传递)
- 中断处理:ISR 要短,耗时操作放任务中,使用 FromISR 版本 API