2.1 整体架构设计


2.1 整体架构设计

本节摘要:RTOS 内核的架构可以概括为一个事件驱动的资源裁决器:硬件抽象层隔离芯片差异,内核五个组件裁决定时与资源,任务与中间件住在内核之上。本节给出分层模型,并沿两条真实调用链走一遍,把「架构」落到可跟踪的函数路径上。

给本节主角下一个可直接使用的定义:RTOS 内核是一个事件驱动的资源裁决器——它不提供任何业务功能,只在「事件到达」与「时间到期」两类时刻出面,决定哪段代码有权使用处理器与共享资源。理解这个定义,分层就不再是背诵用的图,而是裁决权自下而上逐层委托的链条。

分层模型:每层只回答一个问题

成熟的 RTOS(FreeRTOS、Zephyr、RT-Thread 大同小异)都呈现出清晰的四层结构。最底下是移植层,只回答「这块芯片如何保存与恢复现场」:上下文切换的汇编、中断入口与出口、关中断指令、节拍定时器的启动,全部收拢在这一层,换芯片只动它。其上是内核层,五个组件各司其职:调度器管裁决,IPC 管等待与唤醒,内存组件管栈与内核对象的供给,时钟组件管节拍与超时,中断管理管嵌套与延迟切换。再往上是对象与协议层,文件系统、网络协议栈、设备框架以可选组件的形式挂接。最顶上是任务与应用代码。

图:RTOS 分层架构总览

图:RTOS 分层架构总览

分层的好处直接兑现为两个工程事实:移植层稳定后,上三层在不同芯片间零改动;应用层完全不感知芯片,第七章讲的跨核迁移才有操作空间。

走读链路一:时钟节拍如何唤醒任务

第一条链路回答「周期性任务靠什么醒」。硬件定时器每 1 毫秒溢出一次,触发中断;中断入口落在移植层,它保存现场后跳入时钟组件的中断处理函数;时钟组件把节拍计数加一,遍历延时到期列表,把到期的任务从阻塞态移入就绪表,然后设置一个「请求切换」标志;中断退出前检查该标志,若有比被打断任务更高优先级者就绪,则触发 PendSV 类切换异常,由移植层的汇编完成栈切换。整条链路的确定性取决于三个环节的长度都有界:中断入口、到期列表扫描、切换汇编。第六章会逐段测它们的耗时。

走读链路二:一次信号量释放如何生效

第二条链路回答「中断怎么通知任务」。串口接收中断里调用带 FromISR 后缀的信号量释放函数;该函数不直接做任务切换,而是把一个等待者优先级记录到「待处理切换」变量;中断出口处,移植层代码比较这个优先级与被打断任务的优先级,决定是否触发切换。设计意图很清楚:把「调度决策」与「现场切换」从 ISR 中拆出去,挪到中断出口统一做,ISR 因此可以短到只剩取数与通知两步。这两条链路分别覆盖了时间触发与事件触发,其余所有内核行为都是它们的组合。

单内核、微内核与混合形态

分层之上还有个架构选择:内核态里放多少东西。FreeRTOS、Zephyr(默认配置)、RT-Thread 属于单体小内核,五个组件同住一个地址空间,调用是函数跳转,快但隔离弱;QNX、seL4 属于微内核,调度与 IPC 之外全部搬出内核,驱动、文件系统跑成用户态进程,坏一个组件不连累内核,代价是每次跨进程通信多走一轮消息传递;主流商业 RTOS 多取混合——关键路径内核态直达,重服务隔离运行。选型的判据不是新旧,而是你的失效预算:允许驱动崩溃拖垮全系统吗?答案见第七章功能安全一节。

裁剪:架构弹性兑现为配置项

单体小内核的体积弹性来自编译期裁剪。以 FreeRTOS 为例,核心配置集中在一份头文件式的配置表中:

/* 内核能力裁剪示例:最小系统的典型取值 */ #define configUSE_PREEMPTION 1 /* 抢占式调度:截止期防守的前提 */ #define configUSE_TIME_SLICING 0 /* 同优先级不轮转:行为更可预测 */ #define configMAX_PRIORITIES 8 /* 就绪表深度,覆盖任务分级即可 */ #define configUSE_MUTEXES 1 /* 需要优先级继承时打开 */ #define configUSE_TIMERS 0 /* 不用软件定时器则整体剔除 */ #define configSUPPORT_STATIC_ALLOCATION 1 /* 全静态分配,关闭堆管理器 */

关掉时间片轮转、软件定时器与动态堆之后,内核可以压进十几 KB 闪存、几 KB 内存。理解「每个配置项对应哪个组件」比背配置推荐值重要得多——它让你能对着一堆开关说出裁剪后的系统还剩哪些承诺。

本节要点回顾

  • 内核是事件驱动的资源裁决器,分层即裁决权的逐层委托;
  • 移植层收拢全部芯片差异,是跨平台与跨核能力的物质基础;
  • 时钟链路与信号量链路是两类触发的母版,其余行为皆为其组合;
  • 调度决策与现场切换在 ISR 中拆开、在出口统一执行,是短中断的关键设计;
  • 单内核、微内核、混合形态的选择依据是失效预算,不是技术新旧;
  • 裁剪配置与组件一一对应,裁剪的本质是收回对某些截止期的承诺。

常见问题

问:内核态与用户态在无 MPU 的小芯片上怎么实现? 实现不了真正意义上的保护态——没有硬件支持的特权分层,所谓内核态只是软件约定。这也是小内核选择「全部同态加纪律约束」的原因:用编码规范与评审守卫内核数据,而不是指望硬件拦截,5.3 节的软件兜底手段在此生效。

问:分层会不会拖慢关键路径? 分层的开销发生在边界穿越处,而关键路径恰恰设计成少穿越:中断直入服务程序、切换由移植层汇编直达,都是跨层最快的形式。把「关键路径的层数」纳入设计审查,是检验一个内核架构是否健康的快速手段。

问:怎么估算自己项目需要哪些组件? 从时间承诺倒推:有周期性需求就要时钟组件,有多任务就要调度器与 IPC,有外部事件就要中断管理,有动态创建需求才需要堆。第一章的时间指标表,就是组件清单的原始出处——需求里没有的承诺,不要为它付组件的钱。

问:微内核的消息开销到底多大? 数量级上是同进程函数调用的十倍到百倍,取决于消息长度与缓存行为。这个开销买的是隔离与可恢复性,值不值取决于失效预算——7.3 节的等级要求会给出硬性答案,无需凭感觉争论。

再补一条裁剪的实操提醒:裁剪配置的改动要跟随需求变更走变更流程——它比代码更容易被「临时加个功能顺手打开」而无人复审,8.2 节会把它纳入配置纪律。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U