第4章 嵌入式系统软件基础知识

对应教程第4章(约第117~215页)。本章是全教程篇幅最大、考点最密集的章节之一,在下午试题中与"任务调度、同步互斥、存储管理"直接相关的题目几乎年年出现,上午题中也常年占据 6~10 分左右,是必须完整掌握的一章。

本章在讲什么?

前面两章讲的是"看得见摸得着"的硬件,这一章转到软件侧:一个嵌入式系统里,软件到底怎么分层、操作系统到底在忙些什么。本章从嵌入式软件的体系结构讲起(应用层、中间件层、操作系统层、BSP/驱动层),然后花大量篇幅拆解嵌入式操作系统(EOS)的核心职责——任务管理、调度、同步互斥、任务间通信、存储管理和设备管理,最后补充了文件系统和嵌入式数据库两个专题。学习时建议把"任务"当作主线:任务怎么创建、怎么切换、怎么被调度、怎么互相通信,把这条线串起来,本章就活了。

核心概念拆解

4.1 嵌入式软件基础

嵌入式软件的特点:与通用软件相比,嵌入式软件有五个突出特点——

  1. 固化在存储器中:代码通常固化在 Flash/ROM 里运行,而不是像 PC 那样从磁盘加载;
  2. 代码精简、时空效率要求高:存储资源有限,对代码密度和运行速度都敏感;
  3. 实时性要求高:必须在规定时间内完成响应(这也是实时操作系统存在的理由);
  4. 可靠性和稳定性要求高:很多设备 7×24 小时无人值守运行;
  5. 与硬件紧密相关、可移植性要求高:软件要与特定硬件配合,同时又要方便移植到不同硬件平台。

嵌入式软件的分类(考点,常以"下列哪个属于系统软件"形式出题):

分类 内容 举例
系统软件 管理系统资源、为应用提供运行环境 嵌入式操作系统、BSP、设备驱动、文件系统
支撑软件(中间件) 辅助软件开发的工具和中间层 GUI 库、网络协议栈、数据库、CORBA
应用软件 实现具体业务功能 手机上的通话程序、机顶盒的播放程序

嵌入式软件的体系结构:从下到上依次是——设备驱动层(BSP/驱动程序)→ 实时操作系统层(RTOS,含内核、文件系统、网络协议栈等组件)→ 中间件层 → 应用层。层次之间通过接口调用,越往下越贴近硬件,越往上越贴近业务。

考点:BSP(Board Support Package,板级支持包)是介于硬件与操作系统之间的一层,主要包含两大部分:引导加载程序(BootLoader)和设备驱动程序(有的教材还包含初始化代码)。它与 PC 上的 BIOS 的区别是:BIOS 由主板厂商固化提供,而 BSP 由系统开发者根据硬件裁剪编写,且 BSP 在操作系统启动的过程中还要继续发挥作用(BIOS 在操作系统启动后基本不再起作用)。

BootLoader 的两个阶段(高频考点):

  1. Stage 1(汇编阶段,与硬件相关):完成硬件设备初始化(配置 CPU 寄存器、设置时钟、关闭看门狗等)、为加载 Stage 2 准备 RAM 空间、把 Stage 2 复制到 RAM、设置好堆栈后跳转到 Stage 2 的 C 程序入口。
  2. Stage 2(C 语言阶段,与硬件无关):初始化本阶段要用的硬件设备、检测系统内存映射、将内核映像和根文件系统从 Flash 读到 RAM、设置内核的启动参数并调用内核

考点:BootLoader 是在操作系统内核运行之前运行的一小段程序,任务是把内核从 Flash 搬到 RAM 并启动内核。它通常依赖目标机与宿主机配合开发:宿主机(PC)通过串口/网络(常用 TFTP 下载内核、NFS 挂载根文件系统)向目标机传输文件。

设备驱动程序:驱动是直接与硬件打交道的软件层,向上为操作系统提供统一接口,向下控制硬件设备。嵌入式系统中常以模块化方式提供,可动态加载/卸载。

中间件:位于操作系统与应用之间、屏蔽底层差异的软件。常见类别包括消息中间件、数据库中间件、远程过程调用中间件(RPC)、对象请求代理(ORB/CORBA)等。

4.2 嵌入式操作系统概述

作用与特点:嵌入式操作系统(EOS)负责管理系统的软硬件资源,为应用提供运行环境。与通用操作系统相比,EOS 的特点包括:可裁剪/可配置(按需裁剪功能以减小体积)、实时性强高可靠性低功耗可移植性好(内核与硬件相关部分分离,便于移植到不同处理器)。

实时操作系统(RTOS)的关键指标:衡量 RTOS 的核心不是"跑得快",而是"确定性"——即最坏情况下的响应时间可预测。常用指标有:

  • 中断延迟时间:从中断发生到开始执行中断服务程序(ISR)第一条指令的时间;
  • 任务切换时间:从一个任务切换到另一个任务所需的时间。

EOS 的分类(考点):

分类维度 类别 代表
按实时性 硬实时 / 软实时 硬实时如 VxWorks、μC/OS-II;软实例如部分嵌入式 Linux
按使用方式 商用 / 开源 VxWorks、QNX 商用;μC/OS-II、嵌入式 Linux 开源
按内核结构 单内核(宏内核)/ 微内核 Linux 单内核;QNX 微内核
按响应时间 强(硬)实时/弱(软)实时

考点硬实时系统要求任务必须在绝对期限内完成,超时即失败(如飞控、刹车系统);软实时系统允许偶尔超时,只是平均性能下降(如视频播放)。

几种典型 EOS 的对比(常考"下列关于 XX 操作系统的说法正确的是"):

操作系统 主要特点
VxWorks Wind River 公司,硬实时,微内核结构(可选组件),高性能、可裁剪,广泛用于航空、航天、通信等高可靠性领域
嵌入式 Linux 开源免费,可裁剪定制,生态丰富;但标准 Linux 非实时,需打实时补丁(如 PREEMPT_RT)才能满足硬实时
Windows CE 微软推出,组件化、可裁剪,提供与桌面 Windows 相似的开发环境
μC/OS-II 源码公开、结构小巧的抢占式实时内核,基于优先级调度,支持最多 64 个(新版可达 256 个)优先级不同的任务;先占内核(可抢占)
QNX 加拿大 QSSL 公司,微内核结构的硬实时 OS,驱动、文件系统等都作为用户态进程运行,可靠性高
Palm OS 早期 PDA 专用,多任务能力弱,一次只能运行一个应用
Symbian 早期智能手机系统

4.3 任务管理(本章重中之重)

多道程序与并发:现代 EOS 支持多任务并发执行。宏观上并行、微观上串行(单核 CPU 轮流执行)称为并发。

进程、线程与任务

  • 进程:资源分配的基本单位,拥有独立的地址空间和资源;
  • 线程:调度执行的基本单位,同一进程内的多个线程共享该进程的地址空间和资源,但各自拥有独立的栈和寄存器上下文。线程切换的开销远小于进程切换;
  • 任务:嵌入式 RTOS 中对可调度执行实体的称呼,通常就是指"线程级"的实体。一个任务一般由三部分组成:任务控制块(TCB)、任务栈(程序栈空间)和任务函数(代码)

考点:任务的三要素——TCB、栈、代码。TCB 是任务存在的唯一标志,记录任务的标识、状态、优先级、寄存器上下文等管理信息;任务切换时保存/恢复的正是 TCB 中的上下文。

任务的四种状态(高频考点,几乎每年必考状态转换图):

状态 含义
休眠态(Dormant) 任务尚未被创建(或已被删除),只以代码形式驻留内存
就绪态(Ready) 任务已具备运行的全部条件,只等 CPU;被更高优先级抢占或时间片用完后回到就绪态
运行态(Running) 正在占用 CPU 执行;同一时刻只有一个任务处于运行态
等待/挂起态(Waiting/Suspended) 任务因等待某个事件(信号量、消息、延时等)而让出 CPU,事件发生后被唤醒转入就绪态

状态转换要点:就绪 → 运行(被调度);运行 → 就绪(被抢占/时间片耗尽);运行 → 等待(主动等待事件或资源);等待 → 就绪(事件到来);运行 → 休眠(任务删除/自我终止)。

任务切换的时机:中断发生、任务主动延时或等待、高优先级任务就绪引起抢占等。切换过程:保存当前任务上下文到其 TCB → 恢复新任务的上下文 → 跳转到新任务继续执行。

调度算法(高频考点):

算法 思想 特点
FCFS(先来先服务) 按到达顺序调度 简单公平,但对短任务不利,平均周转时间长
SJF(最短作业优先) 优先调度运行时间最短的任务 平均等待时间最优,但长任务可能"饿死"
RR(时间片轮转) 就绪队列轮流执行一个时间片 适合分时系统;时间片太大退化为 FCFS,太小则切换开销大
优先级调度 每次调度优先级最高的就绪任务 RTOS 的主流方式;分为抢占式和非抢占式

考点:RTOS 采用基于优先级的可抢占调度。调度发生时,内核总是让就绪队列中优先级最高的任务获得 CPU。μC/OS-II 中每个任务有唯一优先级,且不支持时间片轮转(同优先级任务不能共存)。

实时调度算法 RMS 与 EDF(下午题常客):

考虑周期性任务集,每个任务用三元组 (S, T, D) 描述——启动时间 S、周期 T、相对截止时间 D。判断任务集是否可调度有两个经典结论:

  • RMS(Rate Monotonic Scheduling,速率单调调度)周期越短,优先级越高(静态优先级,创建时固定)。可调度性判据:当 CPU 利用率满足 U = Σ Ci/Ti ≤ n(2^(1/n) − 1)(n 为任务数)时任务集一定可调度;如 n=2 时上界约 0.828,n→∞ 时上界收敛于 ln 2 ≈ 0.693
  • EDF(Earliest Deadline First,最早截止时间优先)截止时间越早,优先级越高(动态优先级,每次调度时重新计算)。理论最优:只要任务集 CPU 利用率 U ≤ 1(100%),EDF 就能保证所有任务不超期。

考点对比:RMS 静态优先级、实现简单、利用率上界低(最高约 69.3%);EDF 动态优先级、利用率可达 100%、理论最优但实现复杂、瞬时过载时行为不稳定。下午题常给一组周期任务让计算利用率并判断用 RMS 是否可调度。

4.4 同步、互斥与任务间通信

同步与互斥

  • 互斥:多个任务访问临界资源(一次只允许一个任务使用的资源,如打印机)时,必须互斥进入临界区
  • 同步:多个合作任务在执行次序上相互协调,如"任务 A 必须在任务 B 产生数据后才能处理"。

信号量与 P/V 操作(Dijkstra 提出,必考):

  • 信号量 S 是一个整型变量,只能通过两个原语(执行过程不可打断)访问:
  • P 操作(wait/down):S = S − 1;若 S < 0,任务阻塞,进入等待队列;
  • V 操作(signal/up):S = S + 1;若 S ≤ 0,唤醒一个等待任务。
  • S 的物理意义:S > 0 表示可用资源数;S < 0 时其绝对值表示等待该资源的任务数。
  • 互斥:信号量初值为 1(互斥锁),P/V 夹住临界区;同步:按事件先后设置初值(如 0),通过 P/V 控制执行顺序。

考点:P、V 操作必须成对出现;原语的不可分割性保证了操作的安全性。下午题常给一段伪代码让填 P/V 的位置或信号量初值。

死锁:多个任务互相等待对方占有的资源而永久阻塞。产生死锁的四个必要条件(必考):

  1. 互斥:资源一次只能被一个任务使用;
  2. 请求与保持(占有且等待):占有资源的同时又请求新资源;
  3. 不可剥夺:已分配的资源不能被强行抢占;
  4. 环路等待:形成任务—资源的环形等待链。

死锁处理策略:预防(破坏四个条件之一,如一次性申请全部资源破坏"请求与保持"、资源有序分配破坏"环路等待")、避免(银行家算法)、检测与解除鸵鸟策略

优先级反转及其解决(本章特色考点,下午题多次出现):

  • 优先级反转:低优先级任务 L 占有共享资源(互斥锁),高优先级任务 H 申请同一资源被阻塞,而中优先级任务 M 抢占了 L 的 CPU——结果 M 反而先于 H 运行,高优先级被"倒挂"。火星探路者号是经典案例。
  • 优先级继承协议(PIP,Priority Inheritance):H 被 L 阻塞期间,L 临时继承 H 的优先级提升运行,尽快释放资源后恢复原优先级。缺点:若 L 又被更早的低优先级任务阻塞,仍可能出现连锁阻塞,且不能完全避免死锁。
  • 优先级天花板协议(PCP,Priority Ceiling):为每个互斥量设定天花板优先级(等于所有可能申请该资源的任务的最高优先级)。任务获得资源时立即把优先级提升到天花板值。优点是能有效防止死锁和连锁阻塞,但任务提前升优先级可能影响其他中等优先级任务的实时性。

考点对比:继承是"被阻塞后才提升、持锁者被动获得";天花板是"一获得资源就提升到预定值、主动提升"。天花板协议可将阻塞时间控制在一个临界区内。

任务间通信方式

方式 特点
共享内存 多个任务映射同一块内存直接读写,速度最快,但需配合信号量/互斥锁保证一致性
消息队列/消息传递 内核提供缓冲队列,任务间收发消息;无直接共享,安全性好,支持异步通信
管道(pipe) 半双工、字节流的单向通道,先进先出
信号(signal) 异步事件通知机制
邮箱/事件标志 传递单个消息指针或同步事件组合

4.5 存储管理

两种基本模式

  • 实模式(real mode):程序直接使用物理地址访问内存,无保护。简单高效,但没有隔离,一个任务出错可能破坏整个系统;早期 DOS 及部分简单 RTOS 采用。
  • 保护模式(protected mode):引入虚拟地址空间内存保护,CPU 中的 MMU(Memory Management Unit,存储管理单元)负责把虚拟地址翻译成物理地址,并提供权限检查。现代 OS 均采用。

考点:MMU 的两大作用——地址转换(虚拟地址→物理地址)和内存保护。多数低端单片机无 MMU,这类平台上通常只能跑实模式的 RTOS(如 μC/OS-II),有 MMU 的平台才能跑带虚拟存储的嵌入式 Linux。

分区存储管理(把内存划分为若干区域,每个程序占一个连续分区):

  • 固定分区:事先把内存划成大小固定的分区,每个分区装一个作业。实现简单,但会产生内碎片(分区内装不满的部分),利用率低;
  • 可变分区:按需动态划分。无内碎片,但随着分配/释放的进行会产生外碎片(分区之间零散的空闲块)。外碎片可通过拼接(紧凑/移动技术)合并,代价大。

分配算法:首次适应、最佳适应、最坏适应等(这些算法在第1章考试中也常涉及)。

页式存储管理

  • 把进程地址空间和内存都划分为等大的块:进程侧叫页(page),内存侧叫物理块/页帧(frame)。任一页可装入任一物理块,彻底消除了外碎片(仅最后一页有少量内碎片,平均半页)。
  • 页表记录"页号 → 物理块号"的映射;逻辑地址 = 页号 + 页内偏移,由 MMU 查页表完成转换。
  • 为加速转换,使用 TLB(Translation Lookaside Buffer,快表/转换检测缓冲区)缓存最近使用的页表项,命中则免去访问内存查页表的开销。

虚拟存储器

  • 思想:程序装入时不必全部装入内存,只装入当前需要的部分,其余留在磁盘上,用到时再调入。由请求页式管理实现,其页表项需增加"有效位(存在位)、修改位、访问位"等信息。
  • 缺页中断:访问的页不在内存时触发,OS 负责从磁盘把页调入内存;若内存已满,则按页面置换算法淘汰一页。
  • 抖动(颠簸,thrashing):页面频繁地换入换出,CPU 大量时间花在调页上,系统效率急剧下降。

页面置换算法(必考,常给访问序列算缺页次数):

算法 思想 特点
OPT(最佳置换) 淘汰以后最长时间不再使用的页 缺页率最低,但需要预知未来,无法实现,只作评价基准
FIFO(先进先出) 淘汰最早进入内存的页 简单;可能出现 Belady 异常(增加物理块数反而缺页增多)
LRU(最近最久未使用) 淘汰最近最长时间未被访问的页 基于局部性原理,性能接近 OPT,但硬件开销大
LFU(最不经常使用) 淘汰访问次数最少的页 统计访问频度,对"曾热门现已冷"的页不敏感
Clock(时钟/NRU) 用访问位 + 环形指针近似 LRU 指针扫描,访问位为 1 清零继续走,为 0 则淘汰

考点辨析:LRU 看"多久没用"(时间),LFU 看"用了几次"(频率)。OPT 是唯一"向后看未来"的算法。做题时按给定的访问串逐页模拟即可,注意统计"缺页"的定义(首次调入也算缺页)。

4.6 设备管理

I/O 设备的分类:按数据组织分为块设备(以块为单位传输,可随机存取,如磁盘、Flash)和字符设备(按字符流顺序传输,如串口、键盘);按使用特性分为输入设备、输出设备、交互设备、存储设备等。

三种 I/O 控制方式(与第1章呼应,必考):

方式 过程 CPU 利用率
程序查询(轮询) CPU 不停地查询设备状态,忙等数据就绪 最差,CPU 与设备完全串行
中断方式 CPU 发出启动命令后继续干别的,设备就绪后中断CPU,由 ISR 传输数据 提高了并行性;但每传一个字符/数据就要中断一次,开销仍大
DMA 方式 DMA 控制器接管总线,在内存与设备之间直接成块传输数据,完成后才中断 CPU 一次 CPU 干预最少,适合高速块设备

I/O 软件的层次结构(自下而上,必考排序题):

  1. 中断处理程序:I/O 完成后的第一时间响应,唤醒驱动程序;
  2. 设备驱动程序:与硬件直接相关,把上层抽象请求翻译成对控制器寄存器的具体读写命令。典型流程:检查参数 → 检查设备是否空闲 → 发送命令序列 → 若操作耗时则阻塞自己等待中断唤醒 → 完成后检查错误、上传数据、返回状态;
  3. 设备独立的 I/O 软件:系统内核的一部分,实现所有设备通用的功能,包括设备驱动程序的管理(驱动程序地址表,支持动态装卸)统一调用接口(初始化、打开、关闭、读、写、控制)、设备命名与保护缓冲技术出错报告独占设备的分配与释放
  4. 用户空间的 I/O 软件:如 C 库函数(内部转为系统调用)和 Spooling(假脱机)技术

缓冲技术:在内存中开辟缓冲区,缓解 CPU 与外设速度不匹配的矛盾,并利用程序的局部性原理减少对外设的访问。分为单缓冲、双缓冲、多缓冲和环形缓冲

Spooling(假脱机/虚拟设备)技术:用一个专门的 Spooling 程序管理独占设备,应用程序只与 Spooling 的内存缓冲区交换数据(虚拟 I/O),由 Spooling 程序在后台与真实设备交换数据(实际 I/O)。它把独占设备改造成可共享的虚拟设备(如打印机排队打印),提供高速虚拟 I/O 并提高设备利用率。

4.7 文件系统与嵌入式数据库

文件系统:负责组织、存储、命名、使用和保护文件的机制,由管理软件、被管理文件、管理所需的数据结构三部分组成。嵌入式文件系统通常以中间件或应用形式安装在 Flash/RAM 盘上,可裁剪。常见嵌入式文件系统:

  • FAT(File Allocation Table):最常用,与 PC 兼容(FAT12/16/32),VxWorks、QNX、Windows CE 等都支持;
  • NFS:网络文件系统,基于 RPC + XDR,把网络设备像本地分区一样挂载;
  • FFS:Flash 专用文件系统;
  • DosFS:实时条件下的块设备访问;RawFS 把整个磁盘当成一个大文件;TapeFS 把磁带卷当成大文件;CdromFS 遵循 ISO 9660,用于 CD-ROM。

文件的逻辑结构与物理结构:逻辑结构指用户看到的字节流(现代文件系统多采用无结构字节流);物理结构指文件在磁盘上的存放方式,三种(必考对比):

物理结构 思想 优点 缺点
连续结构 逻辑块按顺序存放在连续物理块 支持随机存取、实现简单 外碎片,文件不能动态增长;多用于 CD-ROM/DVD 一次写入介质
链表结构 各块用指针链接,可离散存放 无外碎片、可动态增长 只能顺序访问,随机访问慢
索引结构 每文件的逻辑块号→物理块号记录在索引结点(inode) 支持随机访问、无外碎片 索引本身占空间

链表结构的重要改进是文件分配表(FAT):把散在各块中的指针抽取出来集中成一张内存中的表,随机访问时先查表再直达磁盘,速度大幅提高——这正是 FAT 文件系统名字的由来。

文件控制块(FCB,File Control Block):记录文件所有管理信息的数据结构,是文件存在的标志,含文件的属性信息(类型、长度、所有者、权限、时间戳等)和存储信息(存放位置)。目录的实现分直接法(FCB 内容直接放目录项)和间接法(目录项只存文件名 + FCB 地址)。

空闲空间管理三种方法:位图法(每物理块 1 个 bit,空闲为 1)、链表法(空闲块串成链表)、索引法(用专门的块记录空闲块编号)。

Reliance 文件系统(了解即可):Datalight 公司的事务级文件系统,专为突然掉电的嵌入式产品设计,特点:断电安全重启基于事务处理(在事务点更新数据,断电后恢复到上一稳定状态)、海量记录高效、快速启动(无需 chkdsk 一致性检查)。

嵌入式数据库的特殊要求(了解):

  1. 纯内存工作方式:整个数据处理在内存中完成,消除 I/O 等不确定耗时操作,满足实时性;
  2. 为特殊数据类型提供高效索引:B 树只适合一维数据,二维坐标(如 GPS)用 R 树,多维用 KD 树,还有 T 树、哈希等;
  3. 支持基于优先级的多任务访问:不能简单用 FIFO,需与 OS 任务优先级配合;
  4. 可靠性、持久性和高可用性:类型安全接口(不用 void 指针)、消除动态内存分配、支持主从冗余切换。

典型产品 eXtremeDB:纯内存架构、基于对象模型、非客户/服务器结构;与 Berkeley DB/SQLite"磁盘库加缓存"的做法不同,它是按内存特点重新设计的,支持事务优先级、事务日志恢复和高可用镜像。

初学者容易踩的坑 / 易错考点

  1. 任务状态转换方向记错:等待态被唤醒后是进入就绪态而不是直接进入运行态;时间片用完或被抢占是"运行 → 就绪",任务主动等待事件才是"运行 → 等待"。
  2. RMS 与 EDF 的优先级规则混淆:RMS 是周期短者优先(静态),EDF 是截止时间早者优先(动态)。判断可调度时两者用的利用率判据也不同——RMS 用 n(2^(1/n)−1),EDF 用 100%。
  3. 优先级继承与天花板协议分不清:继承是"阻塞发生后被动提升到阻塞者的优先级",天花板是"一拿到资源就提升到预定天花板",天花板协议还能防止死锁,继承不能。
  4. LRU 与 LFU 弄混:LRU 看"最久未使用"(时间维度),LFU 看"使用次数最少"(频次维度);FIFO 则完全不看访问历史,还要小心 Belady 异常只在 FIFO 中出现。
  5. 内碎片与外碎片张冠李戴固定分区产生内碎片(分区内剩余),可变分区产生外碎片(分区之间零散空闲);页式只有少量内碎片(最后一页),段式偏向外碎片。
  6. I/O 软件层次顺序背反:自下而上是"中断处理 → 设备驱动 → 设备独立 I/O 软件 → 用户空间 I/O 软件"。缓冲管理和设备命名属于设备独立层,而不是驱动层;C 库 printf 属于用户空间层
  7. Spooling 的对象理解错:Spooling 针对的是独占设备(如打印机),把它变成可共享的虚拟设备,应用程序实际是在与内存缓冲区交换数据。
  8. 死锁四条件误选:"资源够用就不会死锁"不是死锁的条件;四条件是互斥、请求与保持、不可剥夺、环路等待,缺一不可,破坏任意一个即可预防死锁。

小结 & 备考提示

本章是嵌入式软件的总纲:从 BSP/BootLoader 这类"贴近硬件的软件",到操作系统的任务管理、同步互斥、存储与设备管理这些"内核机制",再到文件系统和嵌入式数据库。复习时以"任务生命周期"为主线,把状态转换、调度算法、PV 操作、优先级反转这四个下午题高频模块练到能独立手算;上午题则重点抓分类对比表(RTOS 特点、置换算法、I/O 方式、文件物理结构)。

关键词:BSP 与 BootLoader、任务状态与 TCB、RMS/EDF 调度、优先级反转(PIP/PCP)、页面置换算法、FAT 与索引结点