RTOS开篇——逐步带你走进轻量化操作系统的世界!
本文最后更新于116 天前,其中的信息可能已经过时,如有错误请发送邮件到527388734@qq.com

一、引言

之前我反复研读过许多次 FreeRTOS 的源码,每一次深入代码,都会碰撞出新的灵感与惊叹,从而深深被其内部精巧的逻辑所吸引。从这篇文章开始,我将一步步带你从认识到了解,再到自己动手实现一个轻量化的操作系统 RTOS。感兴趣的小伙伴,欢迎随时一起交流技术!

(注:本专题主要以 FreeRTOS 为主线展开讲解,但不会过多涉及 API 接口的具体用法。一方面,这类教程在网上已有不少;另一方面,我更希望帮助大家建立对 RTOS 的感性认识,这样日后系统学习接口时会事半功倍。)

那么,闲话不多说!让我们先聊聊什么是操作系统,算是我们一切的起点。

二、操作系统概念

“操作系统”这个词,相信大家都不陌生。日常生活中我们其实早已与它打过照面——无论是电脑上运行的 Windows、macOS,还是手机里的安卓、鸿蒙,都是操作系统的典型代表。想象这样一个场景:你在电脑前工作时,往往会同时打开好几个软件,比如一边用 WPS 写文档,一边用播放器听音乐,同时浏览器还开着查资料……这些任务看起来在“同时”运行,背后正是操作系统在默默地调度与管理资源,才让我们能够高效地处理多项事务。

这种多任务调度的能力,可以说是操作系统的一个核心概念。当然,我刚才提到的那些都属于功能丰富的大型操作系统,它们集成的模块远不止任务调度,不过那并非本文重点,在此先不展开。总而言之,操作系统本质上是一套管理模式,负责协调设备上各类软件资源的运行,从而让整个系统高效、稳定地工作。

既然操作系统这么强大,我们能不能把它也用到智能嵌入式设备上呢?那样的话,运行效率不就大幅提升了吗?哈哈,完全没有错,但别忘了,嵌入式设备的内存通常只有几 KB 到几 MB,而手机或电脑的存储空间往往以 GB 甚至 TB 计。换句话说,嵌入式设备“装不下”Windows、macOS 这样的庞然大物——不仅存储空间有限,算力也往往不足以驱动如此复杂的系统,就像拖拉机的引擎带不动超跑一样。

三、RTOS引入

那么,难道资源有限的小芯片就注定无法提升运行效率了吗?

关键点来了——正是为了在资源受限、算力有限的嵌入式环境中实现高效调度,RTOS(实时操作系统)应运而生!

RTOS 是专为嵌入式环境设计的轻量化操作系统。它能在有限的 CPU、内存和功耗条件下,实现高效、可靠的多任务调度,并确保任务响应具备实时性与确定性。这不仅大幅提升了芯片的执行效率,更让设备在工业控制、穿戴设备、车载系统等要求严苛的场景中,也能稳定、及时地处理任务。

简单来说,RTOS 让“小芯片”也拥有了“多任务并行”与“实时响应”的“大能力”。

那么接下来,我们就来正式进入 RTOS 的世界!

现在我们已经知道了RTOS能让小芯片实现多任务并发,那么你可能会产生以下疑问:刚刚提到的大型操作系统,他的硬件资源一般都是多核的,一个核运行一个软件程序,从而能够做到多任务并行。但是嵌入式设备一般为了节省能耗只存在一个核,那么他怎么能够做到多个任务同时进行呢?就算一个核运行了多个任务,那么他们之间不会打架吗??

哈哈哈没错,多个任务就是运行在同一个核上的,但是他们不会打架。这就不得不提到RTOS中“错觉”的艺术了。我将举一个很简单的例子,直观带你感受一下何为“错觉”。

比如我们现在正在基于51单片机来进行流水灯程序的设计:

#include <reg51.h>

void delay_ms(unsigned int t) {
    unsigned int i, j;
    for(i = 0; i < t; i++)
        for(j = 0; j < 120; j++);
}

void main() {
    while(1) {
        P1 = 0xFE;  // 11111110b,第一个LED亮
        delay_ms(500);
        
        P1 = 0xFD;  // 11111101b,第二个LED亮
        delay_ms(500);
        
        P1 = 0xFB;  // 11111011b,第三个LED亮
        delay_ms(500);
        
        // ... 继续点亮其他LED
    }
}

上面的例子可以实现一个流水灯的效果,delay_ms(500),可以保证间隔500ms实现对于流水速率的控制。但如果我们仔细看delay_ms这个函数在干什么呢——嵌套了个循环,实质上就是让CPU”数数“(跟我们晚上睡不着属羊一个道理),通过空循环制造出时间差,从而控制流水速度。

但是问题来了,我们再想一下,让CPU数数这个过程有没有什么意义?

是不是感觉特别浪费?觉得完全可以让CPU处理比数数更有意义的事情从而产生一个我们需要的时间差,比如在这个过程穿插数码管显示或者假如传感器数据的采集,是不是都比数数有意义?这样既制造了我们流水所必须的时间差,也在这个时间差中做了更多的事情,使得CPU的效率明显有了一个很大的提升。

其实RTOS中就是用了这个最为核心的思想——让CPU永远去执行更有意义的事情。这里delay_ms有个更为专业的说法叫做阻塞性延时。我们再来看一下RTOS基于这种情况是如何做的:

// 伪代码示例,展示RTOS思想
// 任务1:流水灯控制
void led_task() {
    while(1) {
        P1 = get_next_led_pattern();  // 获取下一个LED亮灭模式
        rtos_delay(500)
        // 在这500ms期间,CPU可以去执行其他任务
    }
}

// 任务2:传感器采集
void sensor_task() {
    while(1) {
        sensor_collect();
        rtos_delay(1000);  // 每1000ms采集一次环境数据
    }
}

// 任务3:数码管显示任务
void seg_task() {
    while(1) {
        seg_display();
        rtos_delay(10);  // 每10ms刷新一次数码管
    }
}

我们可以看到上面有一个关键的一个部分——rtos_delay。他跟我们上面讨论到的delay_ms有本质上的区别,他的意思其实就是”在执行到rtos_delay(500)后,先把当前的任务放下来500ms,这500ms你可以去做其他的事情,500ms时间到了之后再执行一下我就可以了“。这里的rtos_delay是和阻塞性延迟相对的概念——非阻塞性延时。同时我们可以把上面的一个进度描述成一个可视化时间轴:

虽然CPU在任意瞬间只执行一个任务,但通过毫秒甚至微秒级的快速切换,所有任务看起来都在“同时”推进。就像动画片一样——每秒24帧静态画面,我们的大脑却看到了流畅的动作。

这就是RTOS的“并发错觉”!是不是能够初步体会到RTOS的魅力了呢?

RTOS并没有改变硬件只有一个CPU的事实,但它通过精巧的任务调度机制,让每个任务都以为自己独占了CPU。当某个任务需要等待时(比如延时、等待信号量),调度器会立即切换到其他就绪任务,确保CPU永远不“空闲”。

总结一下,这篇文章主要带大家对于操作系统是什么问题以及RTOS如何实现“多任务并行”有了一个最基础的认知,在接下来的文章我将逐步揭开FreeRTOS的内层神秘面纱,直到自己实现一个RTOS,完成任务间的一个初步调度。并以Cortex-M4内核为例,从最底层开始看看他是如何适配FreeRTOS的。

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇