网站软文推广范文杭州滨江建行网站
1. 操作系统
在学习FreeRTOS之前先来了解一下我们平时使用的操作系统到底是什么?
可以用一句话来概括它:
操作系统的本质是一个运行在硬件之上的、系统性的软件程序,它的核心使命是【管理硬件资源,并为软件提供基础服务】,从而在用户/应用程序和计算机硬件之间搭建起一个高效、稳定、安全的桥梁。
首先了解一些操作系统中用到的专业名词,在后续的学习中可以经常回顾复习
1.1 相关专业名词
一、内核与核心概念
操作系统 (Operating System, OS):管理计算机硬件与软件资源的系统软件,为应用程序提供公共服务和执行环境。
内核 (Kernel):操作系统的核心部分,负责管理系统的进程、内存、设备驱动和系统调用,是连接应用程序和硬件的桥梁。
实时操作系统 (Real-Time Operating System, RTOS):保证在指定截止时间内完成关键任务处理的操作系统,其核心特性是响应时间的“确定性”。
调度器 (Scheduler):内核的组成部分,负责决定哪个任务下一步获得CPU的使用权。
系统调用 (System Call):应用程序向操作系统内核请求服务的编程接口,是用户空间访问内核空间的唯一入口。
驱动程序 (Device Driver):一种特殊的软件,充当操作系统与硬件设备之间的翻译官,使操作系统能够控制和管理硬件。
二、硬件相关
单核 (Single-Core):指只有一个物理计算核心的中央处理器(CPU),同一时刻只能执行一个任务。
多核 (Multi-Core):指一个CPU芯片上包含多个独立的计算核心,可以真正并行地执行多个任务。
中断 (Interrupt):硬件或软件发出的一个异步信号,通知CPU需要立即处理某个紧急事件,会暂停当前正在执行的代码。
中断服务例程 (Interrupt Service Routine, ISR):当中断发生时,由CPU跳转执行的特定函数,用于快速处理中断事件。
外设 (Peripheral):计算机系统中除CPU和核心内存之外的其他硬件组件,如GPIO、UART、SPI、ADC等。
三、任务与执行流
进程 (Process):一个正在运行的程序的实例,是操作系统进行资源分配和调度的基本独立单位(拥有独立的内存空间)。
线程 (Thread):进程中的一个执行流,是操作系统进行任务调度和执行的基本单位(同一进程内的线程共享大部分资源)。
任务 (Task):在RTOS(如FreeRTOS)中,这个概念通常等同于线程,是调度的基本单位。
上下文切换 (Context Switching):调度器在切换任务时,保存当前任务状态(寄存器等)、并恢复下一个任务状态的过程。
临界区 (Critical Section):一段必须独占式访问的代码,在执行期间不能被中断或其他任务打断,以防止共享资源被破坏。
四、任务间通信与同步
共享资源 (Shared Resource):可以被多个任务或中断访问的硬件或数据,必须被保护以防止并发访问导致的数据损坏。
互斥量 (Mutex):一种用于实现互斥访问的同步机制,像一个钥匙,只有一个任务能持有它,从而确保对共享资源的独占访问。
信号量 (Semaphore):一种用于控制和同步任务执行的机制,像是一个计数器,管理对多个同类资源的访问或发出事件信号。
队列 (Queue):一种线程安全的先进先出(FIFO) 数据结构,用于在任务之间、任务与中断之间传递消息数据。
事件标志组 (Event Group/Flags):一种同步机制,允许任务等待或操作一组二进制事件标志,用于等待多个事件中的任意一个或全部发生。
五、内存管理
堆 (Heap):一块动态分配的内存区域,允许程序在运行时申请和释放任意大小的内存块。
栈 (Stack):一块连续的内存区域,用于存储函数的局部变量、调用地址等,遵循后进先出(LIFO)原则,每个任务通常都有自己的栈。
内存管理单元 (Memory Management Unit, MMU):一种硬件单元,负责处理CPU的内存访问请求,实现虚拟内存、内存保护等功能(在高端处理器中常见)。
内存保护单元 (Memory Protection Unit, MPU):MMU的轻量版,主要用于嵌入式系统,实现内存区域的访问权限保护,防止任务越界访问。
六、实时性相关
确定性 (Determinism):系统对外部事件的响应时间是可预测和可保证的,这是实时系统的核心要求。
抢占式调度 (Preemptive Scheduling):调度策略允许高优先级任务立即中断(抢占)正在运行的低优先级任务,以保证实时性。
优先级反转 (Priority Inversion):一种不期望发生的情况,即高优先级任务因为等待被低优先级任务占有的资源(如互斥量),而被迫等待,导致中优先级任务先于它运行。
优先级继承 (Priority Inheritance):一种解决优先级反转的算法,当低优先级任务持有高优先级任务所需的资源时,临时提升低优先级任务的优先级。
下面我们来用四个核心维度和一个最终目标来更好地理解操作系统的本质
1.2 操作系统的本质
一、四个核心维度(操作系统的四大管理职能)
管理职能 | 解决的核心问题 | 如何实现(本质行为) |
---|---|---|
1. 进程(任务)管理 | CPU只有单核,如何“同时”运行多个程序? | 抽象(Abstraction):将运行中的程序抽象为进程(或任务),为其分配独立的虚拟CPU和内存空间。 调度(Scheduling):扮演交通指挥官,通过复杂的调度算法(如时间片轮转、优先级调度)在极短的时间内快速切换CPU给不同进程使用,制造出“并行”的假象,实现CPU资源的最大化利用。 |
2. 内存管理 | 内存有限,如何安全高效地分配和回收?多个程序如何共存不冲突? | 隔离与保护(Isolation & Protection):为每个进程分配独立的虚拟地址空间。进程A无法直接访问进程B的内存,就像住在两个平行宇宙,互不干扰,极大提升了系统稳定性。 优化(Optimization):使用虚拟内存、分页、交换等技术,让程序可以使用比物理内存更大的空间,并智能地将常用数据留在内存,不常用的暂存到磁盘。 |
3. 设备(I/O)管理 | 硬件外设(键盘、鼠标、磁盘、网卡)种类繁多,如何简化软件对它们的操作? | 统一接口(Unified Interface):扮演翻译官和中介。提供简单统一的系统调用(如 read , write )来操作所有硬件。应用程序无需关心硬盘是SATA还是NVMe,只需调用 write ,操作系统会通过设备驱动程序将其翻译成硬件能听懂的具体指令。 |
4. 文件系统管理 | 如何长久、有组织地存储大量数据? | 抽象(Abstraction):将复杂的磁盘扇区块管理抽象成用户易于理解的文件和目录结构(如 C:\Users\Doc.txt )。 持久化(Persistence):提供一套机制(文件分配表、inode等)来可靠地存储、查找、读写数据,并管理磁盘空间。 |
二、一个最终目标
所有上述管理职能都服务于一个终极目标:屏蔽硬件的复杂性和差异性,提供一个更简单、更强大、更稳定的虚拟机器(Virtual Machine)抽象。
对用户而言:操作系统提供了图形界面(GUI)或命令行(Shell),让用户无需理解二进制和硬件指令就能使用计算机。
对应用程序开发者而言:操作系统提供了一套稳定、统一的系统调用(System Call)API。开发者无需为不同的硬件重写代码,只需调用
open()
,malloc()
,createThread()
等函数,操作系统会为他们处理好所有脏活累活。
没有操作系统(裸机环境) vs. 有操作系统:
没有操作系统(裸机) | 有操作系统 | |
---|---|---|
编程模式 | 直接操作寄存器,地址“硬编码” | 调用高级API(系统调用) |
资源访问 | 所有软件都能访问所有硬件,极易冲突崩溃 | 硬件访问由OS统一管理,安全稳定 |
并发能力 | 需要开发者自己用超级循环实现,复杂且低效 | OS提供多进程/多线程,并发简单高效 |
开发效率 | 极低,重复造轮子 | 极高,专注于业务逻辑 |
可移植性 | 极差,换块芯片就要重写 | 极好,代码通常无需改动 |
总结
所以,操作系统的本质是:
一个资源管理者:高效、公平、安全地分配和管理硬件资源。
一个抽象层:隐藏硬件细节,向上提供一个清晰、简洁、统一的虚拟机接口。
一个服务提供者:通过系统调用为应用程序提供各种基础服务。
2. 通用操作系统与实时操作系统的区别
特性维度 | 通用操作系统 (GPOS) | FreeRTOS (RTOS) |
---|---|---|
设计目标 | 高吞吐量、公平性、用户体验 | 确定性、可靠性、低延迟 |
核心关注点 | 管理复杂的软硬件资源,为多种应用提供丰富服务 | 确保任务在严格的时间限制内完成 |
应用领域 | 桌面电脑、服务器、智能手机、平板电脑 | 嵌入式系统、物联网设备、工业控制器、汽车电子 |
内核大小 | 非常庞大 (Linux 内核 > 千万行代码) | 极其精简 (FreeRTOS 内核 ~ 万行代码) |
调度策略 | 抢占式 + 时间片轮转,强调公平 | 抢占式,基于优先级,可配置时间片 |
时间确定性 | 非实时。响应时间不确定,受系统负载影响大 | 硬实时或软实时。响应时间有上限保证,可预测 |
内存管理 | 高级且复杂,支持虚拟内存、动态内存分配 | 简单,通常无内存保护单元(MMU),无虚拟内存 |
开发环境 | 功能强大的IDE、图形化调试工具 | 通常与硬件厂商的IDE(如STM32CubeIDE)绑定,调试更底层 |
成本与许可 | 有开源(Linux),也有商业授权(Windows) | MIT 许可证,完全免费,可商用,无需开源自己的代码 |
功能组件 | 自带图形界面、文件系统、网络栈、各种驱动 | 微内核架构,仅提供核心调度、通信、定时器。其他功能(如TCP/IP、文件系统)需以库的形式添加 |
关键差异详解
1. 设计哲学:吞吐量 vs. 实时性
通用操作系统 (Throughput - 吞吐量):它的目标是让整个系统在单位时间内完成尽可能多的任务。比如,你在Linux上一边编译代码、一边听音乐、一边下载文件,OS会努力让所有任务都“感觉”在同时进展,但每个任务的响应时间是不保证的。如果你移动鼠标时正赶上系统在进行大量磁盘I/O,光标可能会“卡顿”一下。
FreeRTOS (Real-Time - 实时性):它的目标不是跑分高,而是保证关键任务一定能在一个确定的时间 deadline 内完成。例如,一个检测汽车刹车信号的任务必须在2毫秒内响应,否则就会发生事故。FreeRTOS会无条件地暂停所有低优先级任务,优先执行这个刹车任务,确保响应时间。
2. 内核与资源:庞大 vs. 精简
通用操作系统:内核庞大,集成了无数驱动和子系统。它运行在资源丰富的环境(GB级内存、GHz级CPU)上,使用虚拟内存(MMU)来隔离进程,一个进程崩溃通常不会导致整个系统崩溃。
FreeRTOS:内核极其精简,通常只有几个C文件,可以运行在资源极度受限的微控制器(MCU) 上(KB级内存、MHz级CPU)。它没有MMU,所有任务共享同一个地址空间。一个任务的指针错误可能会篡改其他任务的数据,导致整个系统崩溃。这就要求嵌入式开发人员有更高的严谨性。
3. 调度策略:公平 vs. 优先级
通用操作系统:采用“时间片轮转”调度。每个任务运行一小段时间(如10ms),然后切换下一个,让每个用户都觉得自己的任务在流畅运行。
FreeRTOS:采用严格的优先级抢占式调度。高优先级任务一旦就绪(例如,因为一个中断信号),会立即抢占低优先级任务的CPU使用权。只有当所有高优先级任务都处于阻塞状态(例如在等待延时或信号量)时,低优先级任务才能运行。
4. 一个具体的例子:处理键盘输入
在 Windows 上:
你按下键盘‘A’键,产生中断。
操作系统 eventually(最终)会处理这个中断,将扫描码放入缓冲区。
当CPU空闲时,键盘驱动处理这个缓冲区,将数据传递给当前前台应用程序(如记事本)。
这个过程可能花费 10ms 或 100ms,取决于系统在忙什么。对你来说,偶尔的延迟是可以接受的。
在搭载 FreeRTOS 的医疗设备上:
患者生命体征监控传感器产生一个中断。
FreeRTOS 会立即暂停当前运行的任何低优先级任务(比如在更新屏幕日志)。
高优先级的“生命体征处理”任务被唤醒,必须在 1ms 内读取传感器数据并进行分析。
如果数据异常,它必须在下一个 1ms 内触发警报系统。
整个过程的最坏响应时间必须是已知且被严格保证的,任何延迟都是致命的。
总结
通用操作系统 (GPOS) | FreeRTOS (RTOS) | |
---|---|---|
核心价值 | “做得更多” (Do more) | “按时完成” (Do it on time) |
思维模式 | 资源共享与公平 | 资源预留与保证 |
适用场景 | 功能复杂、资源丰富的通用计算平台 | 功能专一、资源紧张、时限严格的嵌入式控制领域 |
核心思想:选择RTOS不是因为它的速度快,而是因为它的行为是可知、可控、可预测的。在嵌入式系统中,“对的”时间比“快的”时间更重要。而GPOS则致力于在复杂的通用计算环境中提供最好的整体体验。选择哪一个,完全取决于你的应用场景对时间确定性和资源限制的要求。
3. 多任务处理
3.1 定义
多任务处理是指操作系统的一种核心能力,它使得单个中央处理单元(CPU)能够并发地执行多个独立的任务(进程或线程)。从用户视角看,这些任务像是在同时运行。
3.2 原理
其核心原理是通过时间分片和上下文切换在单个CPU上模拟并行性。
时间分片:操作系统将CPU时间划分为极小的间隔(时间片,如几十毫秒)。每个任务被分配一个时间片来运行。
调度:操作系统的调度器根据特定算法(如优先级调度、轮转调度)从就绪队列中选择下一个要运行的任务。
上下文切换:当切换任务时,内核会保存当前任务的执行状态(上下文)到内存,并恢复下一个任务的上下文到CPU寄存器中。这使得任务能从上次中断的地方继续执行。
硬件支持:依赖定时器中断机制。定期发生的中断使内核获得CPU控制权,从而有机会决定是否进行任务切换。
3.3 意义
提高资源利用率:最大化CPU利用率。当一个任务等待I/O操作(如读写磁盘、网络传输)时,CPU可立即切换到其他任务执行,避免了CPU空闲。
改善系统响应能力:保证了交互式应用程序(如用户界面、游戏)能及时响应用户输入,提供流畅的用户体验,而无需等待后台计算任务完成。
增强系统吞吐量:单位时间内系统能够完成更多的工作量。
实现并发编程:为开发复杂的、需要同时处理多个操作的应用程序(如Web服务器同时处理多个客户端请求)提供了基础模型。
4. 调度器
4.1 定义
调度器是操作系统内核的核心组件,它基于特定调度算法从就绪队列中选择下一个要执行的线程或进程,并为其分配CPU时间。
4.2 调度策略(调度算法)
1. 先来先服务
机制:最简单的一种策略,按照任务到达就绪队列的先后顺序进行调度。这是一个非抢占式的策略。
优点:实现简单,看似公平。
缺点:护航效应显著。如果一个长任务首先到达CPU,那么其后所有的短任务都必须等待长任务执行完毕,导致平均等待时间非常长。对I/O密集型任务不友好(任务在进行I/O操作时会一直霸占CPU等待其完成,而CPU此时是空闲的)。
适用场景:现已很少作为主要策略,主要用于辅助或背景计算。
2. 最短作业优先
机制:优先调度预计运行时间最短的任务。这需要预知每个任务的运行时间,实践中通常需要预测。
优点:理论上可以给出最短的平均周转时间(任务从提交到完成的总时间)。
缺点:
无法预知未来:任务的运行时间很难准确预知。
可能导致饥饿:如果不断有短任务到达,长任务可能永远得不到调度。
适用场景:批处理系统,其中作业长度相对可知。
3. 优先级调度
机制:为每个任务分配一个优先级。调度器总是选择当前就绪队列中优先级最高的任务运行。
静态优先级:任务在创建时分配优先级,且终身不变。简单但不灵活。
动态优先级:调度器根据任务的运行情况(如等待时间、已占用CPU时间)动态调整其优先级。这是现代系统的常用技术。
优点:能明确区分任务的紧急程度,处理关键任务。
缺点:
饥饿:低优先级任务可能永远无法运行。
优先级反转:一个低优先级任务持有一个高优先级任务所需的资源,导致中优先级任务抢先执行,从而间接阻塞了高优先级任务。
适用场景:实时系统、以及作为其他复杂策略的基础组件。
4. 时间片轮转
机制:专为分时系统设计。为每个任务分配一个固定的、最大长度的CPU时间(称为时间片)。任务在时间片内运行,时间用完后被抢占,并放回就绪队列的末尾,接着调度下一个任务。
优点:对所有任务绝对公平,能保证每个任务都能定期获得CPU时间,响应性好。
缺点:性能严重依赖于时间片的大小:
时间片太长:退化为FCFS,响应性变差。
时间片太短:上下文切换频繁,系统开销巨大,吞吐量下降。
适用场景:交互式系统(如通用操作系统),是公平性的基石。
5. 多级反馈队列 - 现代操作系统的综合策略
机制:这是多数现代操作系统(如Linux、Windows)实际采用的综合策略。它结合了以上策略的优点,其核心思想是:
设立多个就绪队列,每个队列有不同的优先级和不同的时间片长度。高优先级队列的时间片通常较短(为了快速响应),低优先级队列的时间片较长(为了减少开销,提高吞吐量)。
新任务首先进入最高优先级队列。
如果一个任务在时间片内完成了,它可能顺利结束。这通常是短作业、交互式任务(如键盘响应)。
如果一个任务用完了它的时间片还没放弃CPU(即它是CPU密集型任务),则被降级到低一级的优先级队列中。
如果一个任务在时间片用完前主动放弃CPU(例如进行了I/O操作,这是交互式任务的典型行为),则说明它可能是交互式任务,其优先级得以维持或甚至提升,以免其饥饿。
为了防止低优先级任务完全饥饿,系统可以实施老化策略:将等待时间过长的低优先级任务提升到高优先级队列。
优点:
对短作业、交互式任务友好(它们能快速获得响应并在高优先级队列中完成)。
对CPU密集型的长作业也能公平处理(它们会沉到底层,享用大时间片,虽然调度频率低但一次执行时间长)。
无需预知任务的运行时间,能根据任务的实际行为(是I/O密集型还是CPU密集型)动态调整其优先级。
缺点:实现复杂,需要调整的参数较多(队列数量、各级时间片大小、升级/降级规则等)。
适用场景:几乎所有通用的交互式操作系统。
4.3 FreeRTOS的调度策略
抢占式优先级+时间片轮询
抢占式调度:
在 抢占式调度 模式下,FreeRTOS 会根据任务的 优先级 来自动决定哪个任务运行。如果一个高优先级任务变为就绪状态,它会立即抢占正在运行的低优先级任务的 CPU 控制权。任务的切换是由调度器决定的,而不是由任务自己控制。抢占式调度模式支持优先级抢占,即系统总是让优先级最高的任务先执行,无论当前是否正在执行其他任务。
时间片轮询调度(Round-Robin):在抢占式优先级调度的基础上,FreeRTOS 还可以通过时间片轮询调度来分配同一优先级下任务的执行时间。当多个任务具有相同优先级时,调度器会按轮流的方式让这些任务分别执行一定的时间片。
每个任务会在自己被调度执行时,运行一个预设的时间片(通常是一个定时周期),如果时间片用尽而任务还没有执行完,调度器会将控制权交给其他任务,之后再轮回回来给该任务执行。综合起来:
抢占优先级调度 是 FreeRTOS 的核心,确保高优先级任务能够优先执行。
时间片轮询 是一种针对同优先级任务的公平调度方式。对于同一优先级的任务,FreeRTOS 会以时间片的方式轮流调度它们。
5. FreeRTOS的调度原理
FreeRTOS的任务调度采用基于优先级的抢占式调度机制,其核心原理是调度器始终从就绪队列中选择优先级最高的任务来执行。当更高优先级的任务就绪时,它会立即抢占当前运行的任务,实现实时响应;同时通过时间片轮转机制,让同优先级的任务公平分享CPU时间。任务在执行过程中可能因等待资源而进入阻塞状态,或因主动延时而暂停,此时调度器会将CPU使用权交给其他就绪任务,并通过系统时钟节拍(Tick)来管理任务的时间片和唤醒时机,从而确保多任务环境下的高效运行和实时性要求。
任务(Task)
FreeRTOS中,程序的执行单元被称为“任务”(Task),它类似于传统操作系统中的“线程”。任务是操作系统的基本调度单元,它的执行由操作系统的调度器控制。每个任务都有一个优先级和一定的执行周期。
任务状态
1. 运行态 (Running)
描述:任务正在实际执行,CPU 的 Program Counter 正指向它的代码。在单核CPU中,任何时候都只有一个任务处于运行态。
好比:绿灯亮起,一辆车正在通过路口。
如何进入:
被调度器从就绪态中选中执行。
2. 就绪态 (Ready)
描述:任务已经准备就绪(不再被阻塞),随时可以运行,只是还没有被调度器选中。所有就绪的任务会被放在一个叫就绪列表的队列中,调度器根据优先级从这个列表里挑选下一个要运行的任务。
好比:车辆在路口等绿灯,已经挂好档,只要绿灯一亮就能走。
如何进入:
任务被创建后默认进入就绪态。
从阻塞态转换而来(等待的事件发生了,如延时到期、收到信号量)。
从挂起态被恢复 (
vTaskResume
)。一个更高优先级的任务从阻塞态进入就绪态,会抢占当前运行态的任务,使其回到就绪态。
3. 阻塞态 (Blocked)
描述:任务在等待某个事件,在事件发生之前无法运行。处于阻塞态的任务不会被调度器考虑。这是实现高效CPU利用的关键状态,因为任务可以在等待时主动让出CPU。
好比:司机在等红灯或等朋友上车。在等待期间,他不需要踩油门,可以把车停在路边(让出CPU)。
如何进入:
调用
vTaskDelay()
等待一段时间。尝试获取一个暂时不可用的信号量、互斥锁、队列。
等待任务通知等事件。
如何离开:
延时到期(如果是因为
vTaskDelay
进入的)。等待的事件发生了(如信号量可用、队列收到数据)。
4. 挂起态 (Suspended)
描述:任务被主动强制地暂停,进入“休眠”。它既不被调度器调度,也不会等待任何事件。只有通过明确的命令才能将其唤醒。这个状态不会超时自动退出。
好比:司机把车熄火停进了车库。它不会自己开出来,必须有人去车库里重新启动它。
如何进入:
被其它任务或自身调用
vTaskSuspend()
函数挂起。如何离开:
被其它任务或中断调用
vTaskResume()
或xTaskResumeFromISR()
函数恢复。5. 删除态 (Deleted)
描述:任务已被
vTaskDelete()
函数删除。它的代码依然保存在Flash中,但内核已为其分配的内存(TCB任务控制块和栈空间)会被释放回收。好比:车辆被报废回收了,它的车位(内存)可以停别的车了。
状态转换 如何实现(API函数) 说明 运行 -> 阻塞 vTaskDelay()
,xQueueReceive()
,xSemaphoreTake()
任务主动让出CPU,进入等待。这是良好FreeRTOS编程的关键! 阻塞 -> 就绪 延时到期、 xQueueSend()
,xSemaphoreGive()
由内核或其它任务/中断触发事件。 就绪 -> 运行 调度器自动完成 调度器选择最高优先级的就绪任务执行。 运行 -> 就绪 调度器自动完成 被更高优先级任务抢占。 任何 -> 挂起 vTaskSuspend()
强制暂停一个任务。 挂起 -> 就绪 vTaskResume()
强制恢复一个任务。 任何 -> 删除 vTaskDelete()
删除任务,释放内存。
任务队列
队列类型 英文名称 作用描述 就绪队列 Ready Queue 存放所有准备运行、等待被调度器选择执行的任务 阻塞队列 Blocked Queue 存放因等待资源或延时而被阻塞的任务 挂起队列 Suspended Queue 存放被主动挂起、不参与调度的任务
优先级(Priority)
FreeRTOS中的每个任务都有一个优先级,任务的优先级是调度器进行任务选择的关键因素。任务优先级的范围一般是0到configMAX_PRIORITIES - 1(在FreeRTOSConfig.h文件中可以配置configMAX_PRIORITIES的值,通常是10或更多)。
任务的优先级有以下几个特点:
优先级高的任务将优先于低优先级任务执行
在抢占式调度模式下,优先级高的任务会抢占当前正在执行的低优先级任务
在协作式调度模式下,任务必须主动放弃CPU,优先级高的任务只有在低优先级任务主动让出CPU时才会执行
时间片(Time Slice)
FreeRTOS的调度器通常不会对每个任务设置严格的时间片,但如果配置了时间片机制(比如在某些调度策略下),任务会在其时间片内执行一段时间后主动放弃CPU,转而让其他任务运行。FreeRTOS默认是没有时间片机制的,但通过vTaskDelay()或者任务调度器的设置,可以模拟时间片的效果。
时间片和Tick
FreeRTOS基于系统时钟(通常由定时器产生)进行时间管理。每当时钟中断触发时,调度器会调用xPortSysTickHandler(),这个函数会更新系统时间和触发任务调度。
在FreeRTOS中,系统时钟中断的周期称为Tick。configTICK_RATE_HZ参数在FreeRTOSConfig.h文件中定义,它决定了时钟中断的频率。例如,如果configTICK_RATE_HZ设置为1000,则每秒钟会触发1000次时钟中断,即每个Tick的周期是1ms。
上下文
在FreeRTOS中,上下文(context)通常指的是任务(线程)执行的状态信息,包含了任务运行时的寄存器值、栈指针等。在操作系统层面,每个任务都有自己的上下文,当任务从一个状态切换到另一个状态时,操作系统需要保存当前任务的上下文,并加载新任务的上下文。这一过程被称为上下文切换(Context Switch)。
FreeRTOS中的上下文管理
1. 任务上下文
每个任务都有自己的栈,栈中保存了任务的局部变量、函数返回地址、寄存器值等信息。任务的上下文在任务切换时保存与恢复。
2. 上下文切换(Context Switch)
在FreeRTOS中,上下文切换发生在任务调度时。当高优先级任务需要执行时,操作系统会保存当前任务的上下文,并加载下一个任务的上下文。
FreeRTOS使用一个叫做"任务控制块(TCB)"的结构体来管理每个任务的上下文信息,TCB保存了任务的栈指针、优先级、任务状态等信息。
3. 上下文切换的过程
当任务切换时,操作系统会通过保存当前任务的寄存器值(包括程序计数器PC和堆栈指针SP)来保存上下文
然后,它加载下一个任务的寄存器值,恢复其栈指针,从而使下一个任务恢复执行
4. 中断处理与上下文切换
在FreeRTOS中,中断也会引发上下文切换。当中断发生时,当前任务的上下文会被保存,并执行相应的中断服务程序(ISR)。ISR执行完毕后,会根据中断发生时的任务优先级决定是否需要进行任务调度(也就是是否进行上下文切换)。
5. 任务调度器(Scheduler)
FreeRTOS使用时间片轮转调度、优先级调度等算法来决定哪个任务获得CPU时间。上下文切换是由调度器触发的,当一个任务执行完时间片,或者高优先级任务就绪时,调度器会触发上下文切换。
总结
在FreeRTOS中,上下文主要指任务的执行状态,包括寄存器、栈指针等信息,任务切换时会保存和恢复这些信息。上下文切换保证了多任务环境中每个任务的独立性和合理的资源分配。
空闲任务
特性 描述 优先级 0(最低) 创建时机 调用 vTaskStartScheduler()
时自动创建主要职责 内存清理、低功耗管理、后台处理 执行条件 没有其他就绪任务时 配置选项 通过 FreeRTOSConfig.h
配置