自顶向下学习RTOS第0讲-RTOS起源

1 RTOS的核心

嵌入式RTOS(实时操作系统),市面上有很多款不同的RTOS,如:

  1. FreeRTOS
  2. UCOSII
  3. RT-thread
  4. Huawei LiteOS
    等等...

初次听说这么多名字不同的RTOS,容易让人眼花缭乱,难以把握它们的本质,本篇希望能从“第一性原理”出发,先提炼出RTOS的本质,然后从本质出发,分析对比不同RTOS的实现方式,进而达到完全掌握RTOS的目的,正所谓“万变不离其宗”。

归根结底,RTOS的核心:

1. 多任务
2. 任务间的通信

(不含其它协议栈如lwip/Fatfs/usb等协议栈)

RTOS正是围绕这两点进行构建的。

2 关于RTOS的几个问题

问题1:为什么要有多任务?
做个类比:人也是个多任务系统,在眼睛观察的同时,耳朵、鼻子、手、脚等可能同时在工作;同样,作为复杂一点的嵌入式系统,需要同时处理多个任务,比如手机可以边放音乐、边浏览网页、微信边在后台收消息,这都离不开多任务操作系统支持。

问题2:嵌入式多任务不用RTOS行不行?
简单的嵌入式常用前后台系统:
前后台系统:大循环 + 中断

中断在前台:                             大循环在后台:
中断处理函数中触发对应的条件标记         
                                        while (1) {
条件1_IRQ(void)                              if (条件1)
{                                            {   
        条件1 = True;                            task1();        
}                                            }

条件2_IRQ(void)                              if (条件2)
{                                            {
        条件2 = True;                            task2();
}                                            }

条件3_IRQ(void)                              if (条件3)
{                                            {            
        条件3 = True;                            task3();
}                                            }  
...                                          ...
                                         }

前后台系统的优点:

简洁,明了,几乎不需要RAM/ROM的额外开销,一些简单的嵌入式系统这么做很方便。

当场景变复杂,任务比较多,前后台系统弊端也较明显,如下:

  1. 如果上述代码条件1、条件2、条件3都成立,只能等着task1完成后,执行task2,然后执行task3,这样就相当于批处理系统,缺点是作业周转时间长,如果task1很耗时,后面的任务只有等待,所有任务相当于同一优先级,一些关键任务实时性无法保证。
  2. 如果任务中有延时,cpu只能空转死等,无法切给其他任务用,cpu利用率低。
  3. 当任务多且任务之间依赖较多,前后台系统会很复杂,原因是:前后台系统是强迫人像机器一样顺序思考,写出顺序结构的代码,而采用RTOS则是多任务的,比较适合人类思维。

引入RTOS后:
第一个问题由时间片或者任务优先级解决;
第二个问题由系统延时解决;
第三个问题RTOS通过"虚拟"CPU,让所有任务认为自己“独占CPU”。
(实际上只有一个CPU,采用分时复用,宏观上并行,微观上还是串行,任务好像在"独占CPU")
后续章节将会解释解决方案。

3 RTOS的多任务

多任务的切换其实就是不同任务运行环境的切换。所以为了保证任务切换出去后,经过一段时间再切换回来能够继续往下执行,需要在切换之前保存当前任务的运行环境。

问题是要保存哪些东西?简单来说:保存可能被改变的东西

粗略列一下:

  1. cpu的寄存器(如PC,状态寄存器,数据寄存器等)---- 需要保存,因为新任务也要用
  2. 栈寄存器(BP与SP等)---- 需要保存,因为堆栈中保存着局部变量,属于任务私有
  3. 代码段,数据段等 ---- 不需要保存,因为它们不会被新任务覆盖

有时间可以分析一下C语言的函数调用,其底层其实就是栈帧切换过程,RTOS多任务切换与函数调用过程很类似:都需要保存cpu的寄存器,差别是:单任务系统函数调用只有一个调用栈(所以不需要保存),而RTOS多任务系统每个任务都需要保存独立栈空间。

RTOS多任务也采用单个栈行吗?
答案是不行,考虑多个任务如A, B, C,切换顺序可能是A->B->C->A->C->B 等,不满足栈的先入后出特性。

4 RTOS的任务间通信

多任务之间要进行通信,可以采用如下方式:

  1. 全局变量
  2. 信号量
  3. 消息邮箱
  4. 消息队列

这些通信方式都是必须的吗?它们之间差别是什么?见后续章节。

5 参考

  1. 自己动手从0到1写嵌入式操作系统
  2. 从0开始,动手创建一个自己的RTOS
  3. LiteOS 开发指南
  4. 孟老师讲Linux内核
  5. 浅谈Linux 中的进程栈、线程栈、内核栈、中断栈
  6. 主流嵌入式操作系统(RTOS)有哪些?看看这14种
posted @ 2022-02-26 23:06  sureZ_ok  阅读(311)  评论(0编辑  收藏  举报