很多初学嵌入式的人第一次接触RTOS时,都会看到一些概念:
- Task(任务)
- Scheduler(调度器)
- Ready List(就绪队列)
- Tick(系统节拍)
但是这些概念到底是如何工作的?
如果直接阅读FreeRTOS等大型RTOS源码,会因为代码量太大而难以理解。
因此,本文通过一个简单的8051协作式调度器,分析RTOS最核心的运行机制。
本文代码来自HRTOS早期调度核心。
项目地址:
HRTOS官网:
HRTOS - Hard Real-Time Operating System | 硬实时操作系统
一、RTOS本质是什么?
很多人认为RTOS就是“同时运行多个程序”。
实际上,单片机通常只有一个CPU核心,同一时间只能执行一个任务。
RTOS做的事情其实是:
在不同任务之间快速切换,让多个任务看起来像同时运行。
例如:
任务1:LED闪烁 任务2:串口通信 任务3:按键检测调度器负责决定:
下一次CPU应该运行哪个任务。
二、最简单的任务管理结构
HRTOS使用任务控制块(TCB)保存任务信息。
例如:
OS_TCB xdata os_task_table[OS_MAX_TASK];任务表保存:
- 任务ID
- 任务入口地址
- 等待时间
- 任务状态
可以理解为:
任务表 +------------+ | Task 0 | +------------+ | Task 1 | +------------+ | Task 2 | +------------+每个任务都有自己的管理信息。
三、就绪任务如何保存?
HRTOS使用位图管理任务状态:
unsigned int os_ready_bitmap;例如:
bit: 0000 0111 表示: Task0 就绪 Task1 就绪 Task2 就绪 其他任务 未运行相比遍历整个任务列表,位图方式更加适合资源有限的8051。
四、创建任务
任务创建函数:
char os_task_create( unsigned int addr, unsigned char id, unsigned char pr, unsigned char sd )核心代码:
os_task_table[id].id=id; os_task_table[id].addr=addr; os_ready_bitmap|=(1 << (id));这里完成三个动作:
- 保存任务入口地址
- 分配任务ID
- 加入就绪队列
例如:
创建LED任务:
os_task_create( LED_task, 1, 0, 0 );系统之后就知道:
Task1在哪里,需要运行时跳转过去。
五、任务等待机制
RTOS中经常需要:
“等待一段时间后继续运行”。
例如:
LED每500ms翻转一次。
HRTOS:
os_wait(type,obj,tick);核心:
os_task_table[os_current].wait_tick=tick; os_ready_bitmap &= (~(1 << os_current));意思是:
当前任务进入等待状态。
同时:
从就绪列表中删除。
CPU可以运行其他任务。
六、系统节拍Tick如何唤醒任务?
8051定时器中断:
void wake_task() interrupt 1每次中断:
检查所有任务:
if(os_task_table[i].wait_tick) { os_task_table[i].wait_tick--; if(os_task_table[i].wait_tick==0) { os_ready_bitmap|=(1<<i); } }例如:
Task1等待5个tick:
tick5 ↓ tick4 ↓ tick3 ↓ tick2 ↓ tick1 ↓ 0 ↓ 重新加入就绪队列这就是RTOS中的时间管理。
七、最核心的调度器
调度器:
void os_schedule()它负责选择下一个任务。
核心逻辑:
for(i=os_current+1;i<OS_MAX_TASK;i++) { if(os_ready_bitmap&(1<<i)) { break; } }简单来说:
从当前任务之后寻找下一个可运行任务。
例如:
当前:
Task0运行就绪:
Task1 Task3调度:
Task0 ↓ Task1 ↓ Task3 ↓ Task0这就是最基本的轮询调度思想。
八、为什么这是协作式调度?
这个版本属于协作式调度。
特点:
任务主动让出CPU。
例如:
while(1) { LED(); os_wait(...); }任务调用等待函数后:
CPU才会切换任务。
优点:
- 实现简单
- 代码量小
- 非常适合学习RTOS原理
缺点:
如果某个任务:
while(1) { do_something(); }一直占用CPU,不主动释放。
其他任务就无法运行。
九、从协作式到抢占式
现代RTOS通常采用抢占式调度。
区别:
协作式:
任务主动释放CPU Task A | wait() | Task B抢占式:
定时器中断触发 Task A | 中断 | 调度器 | Task BHRTOS后续版本在这个基础上增加了:
- 优先级调度
- 抢占式切换
- 多级任务管理
十、总结
通过几十行核心代码,可以看到一个RTOS最基础的组成:
任务管理 | 任务状态 | 时间管理 | 调度器 | 任务切换RTOS并不是神秘的软件。
它本质上就是:
管理多个任务,并决定CPU下一步执行谁。
对于8051这种资源有限的MCU,通过简单、高效的设计,同样可以实现实时任务管理。
更多HRTOS资料:
HRTOS - Hard Real-Time Operating System | 硬实时操作系统
https://hrtos.cn
欢迎交流8051、RTOS以及嵌入式系统开发。