第五章 · 内存管理 本章要回答的三个问题:为什么实时系统对动态内存分配如此警惕,malloc 到底慢在哪、险在哪?栈、静态池、分块堆各该装什么,边界怎么划?碎片是怎么长出来的,哪些策略能让它长不出来? 为什么会有这一章 通用软件世界里,内存分配是理所当然的服务:要多少给多少,用完还回去。嵌入式实时世界里它却成了争议中心——不少团队的编码规范直接写着「禁用 malloc」。这个禁令不是教条:每一次动态分配都同时带来时间的不确定(找一块合适的空闲块要多久没人敢保证)与空间的隐患(碎片让系统在运行数周后明明总余量充足却分配失败)。对截止期防守而言,这两条都是直接威胁。 本章把内存问题拆成三节。5.1 节讲分配策略:从全静态到五种堆管理器的取舍,回答「什么时候可以分配、在哪里分配」。5.
本章要回答的三个问题:为什么实时系统对动态内存分配如此警惕,malloc 到底慢在哪、险在哪?栈、静态池、分块堆各该装什么,边界怎么划?碎片是怎么长出来的,哪些策略能让它长不出来?
通用软件世界里,内存分配是理所当然的服务:要多少给多少,用完还回去。嵌入式实时世界里它却成了争议中心——不少团队的编码规范直接写着「禁用 malloc」。这个禁令不是教条:每一次动态分配都同时带来时间的不确定(找一块合适的空闲块要多久没人敢保证)与空间的隐患(碎片让系统在运行数周后明明总余量充足却分配失败)。对截止期防守而言,这两条都是直接威胁。
本章把内存问题拆成三节。5.1 节讲分配策略:从全静态到五种堆管理器的取舍,回答「什么时候可以分配、在哪里分配」。5.2 节讲碎片:它是怎么从一长一短的分配模式里长出来的,外部与内部碎片的差别,以及让系统终身无碎片的组合拳。5.3 节讲保护:内存保护单元与虚拟内存在实时系统里的受限用法——不是照搬桌面世界,而是取其隔离之长、去其不确定之短。
| 节号 | 回答的问题 | 关键产出 |
|---|---|---|
| 5.1 实时内存分配策略 | 从哪里拿内存,每种来源的时间特征 | 分配路线对比与五种堆管理器选型 |
| 5.2 碎片控制与优化 | 碎片如何产生,如何让它绝迹 | 碎片成因模型与工程组合拳 |
| 5.3 保护单元与虚拟内存 | 隔离怎么做,虚拟内存取什么舍什么 | 保护单元配置思路与受限虚拟内存用法 |
三节是递进关系:先解决「有没有确定性的来源」,再保证「来源长期可用」,最后给系统加上「越界也有底」的保护。
需要 3.1 节的栈知识(预算与水印检查)、2.2 节的三路内存供给划分。5.3 节涉及虚拟内存的基本概念,用到时会就地解释。
一块典型微控制器的内存,在 RTOS 系统里被划成四个区域,各自的服务对象与时间特征都不同——这张划分图是三节内容的总纲:
读图要点在右列:从上到下,分配行为的确定性递减。第五章的努力方向,就是把尽可能多的需求从最下一行挪到上面三行。
内存供给理顺之后,第六章进入时间敏感度的另一个极端——中断与时钟:微秒级的响应预算里,每一拍都在跟内存之外的硬件资源打交道。而 5.1 节埋下的池加指针模式,正是 6.1 节中断管线推荐的数据结构。
第五章的方法最终要落成一份内存预算表,编制方法如下。按对象家族分行列出:每个家族(报文缓冲、协议上下文、显示帧)标注供给来源(静态、池、堆)、块尺寸、深度或总量、耗尽策略与验证方法。栈单独成节:每个任务的初值、水印实测值与余量比。汇总处算两个总数:静态占用(链接期确定)与运行期峰值占用(预算确定),对照芯片容量留出至少四成余量给未知需求。
预算表最大的价值是让「内存不够」成为设计阶段就暴露的问题,而不是测试阶段的事故。经验上,首次编制常发现两类问题:某些对象家族根本没有被意识到(日志缓冲是惯犯),以及某些池深度拍脑袋过大挤占了别人。发现得早,都是改一行表格的事。