存储器层次与内存布局概念
建立"寄存器→Cache→内存→外存"金字塔概念,知道程序运行时的内存五区划分
- 来源
标记说明:【来源】来自上传资料 · 【补充】课程新编 · 【纠错】按勘误表修正 · 【更新】过时内容已现代化 · 【待确认】无法可靠还原
完成标准(本章)
- 📖 已阅读:滚动 ≥ 80% 且有效阅读 ≥ 90 秒
- ✏️ 已练习:小练习正确率 ≥ 60%
- 📝 已通过测验:分数 ≥ 60 分
- 🛠️ 已掌握还需完成实践任务
0.1.4 存储器层次与内存布局概念
本章来源:存储层次与内存五区来自《第一阶段讲义》8.1/8.2/8.5/10.5 节【来源】,重新组织表述;类比与练习为新编【补充】。Cache 细节与 MCU 内存类型在 7.1 深化。本章无代码(概念章),平台适用性 universal。
① 学习目标
- 画出"寄存器→Cache→内存→外存"的金字塔,并说出各层在速度/容量/价格上的规律;
- 说出 RAM(易失)与 Flash(非易失)的区别及嵌入式中的分工;
- 说出程序运行时的内存五区与各区存放内容;
- 完成 15 个典型对象的五区归类(实践任务);
- 能向别人解释"栈小堆大、栈快堆慢"的原因。
② 前置知识
- 建议:0.1.1(五大部件中的存储器)、0.1.3(补码——本章会涉及"数据以二进制位存放")。
③ 核心概念【来源】
| 概念 | 说明 |
|---|---|
| 存储层次 | 寄存器 > Cache(L1/L2/L3) > 内存 > 外存;越靠近 CPU 越快越小越贵 |
| 局部性原理 | 时间局部性(刚访问的很快再访问)与空间局部性(相邻数据连续访问)——Cache 的依据 |
| 易失/非易失 | RAM(SRAM/DRAM)掉电丢失;Flash/磁盘掉电保持 |
| NOR vs NAND | NOR 可随机读取、可存代码(XIP);NAND 容量大、按块访问、适合大数据 |
| 内存五区 | 代码区 / 常量区 / 全局·静态区(.data/.bss)/ 堆区 / 栈区 |
| 栈向低地址、堆向高地址 | 经典进程布局:两者相向增长 |
④ 通俗解释【补充】
把"取用数据"想象成办公:
- 寄存器 = 手边的草稿纸:伸手就能写,但只有几张;
- Cache = 桌面文件盒:比手边大一点,放最近用过的文件(局部性);
- 内存 = 身后的文件柜:容量可观,起身走两步;
- 外存(SSD/Flash) = 楼下的仓库:几乎无限大,但取一次要下楼。
越常用的放得越近——这就是存储层次的全部设计思想。而"程序运行时的内存"就是那组文件柜的分格:代码区放操作手册(只读)、常量区放铭牌、全局区放公司公告(人人可见、长期有效)、堆区放临时租来的大箱子(用完要还)、栈区放接待台上的便签(人来放、人走收)。
⑤ 示例代码
本章为概念章,无代码示例。五区布局的直接验证(打印变量地址对比)见 1.3.1 指针基础。
⑥ 编译与运行方法
本章无代码。
⑦ 常见错误
| 症状 | 原因 | 解决 |
|---|---|---|
| 认为"程序存在硬盘,CPU 直接读硬盘执行" | 忽略内存中转 | 程序先加载进内存,CPU 与内存/缓存交互 |
| 把字符串字面量说成栈变量 | 字面量只读、存常量区 | 字面量在常量区,指向它的指针在栈 |
| 把 static 局部变量归到栈 | static 改变生命周期 | static 局部变量在全局/静态区,生命周期整个程序 |
| 混淆 NOR/NAND 用途 | 未记准随机访问差异 | NOR 存代码(随机读),NAND 存数据(块访问、容量大) |
| 认为 MCU 里堆栈也像 PC 一样大 | PC 与 MCU 资源量级不同 | MCU 栈常以 KB 计:深递归、大局部数组要警惕 |
⑧ 小练习
小练习
学习自测:提交后才显示答案与解析(前端判分,不作为正式考试)ex-0-1-4-1.存储层次中,速度最快、容量最小的一层是?(单选)
◌ 未作答ex-0-1-4-2.程序运行时,局部变量存放在内存的哪个区域?(单选)
◌ 未作答ex-0-1-4-3.判断:断电后 RAM 中的数据会丢失,Flash 中的数据不会。(判断)
◌ 未作答
⑨ 章节测验
章节测验
⑩ 实战任务
实践任务
制作"内存五区"速查卡片并完成归类练习
制作一张内存五区速查卡(区域名/存放内容/生命周期/增长方向),并用它对 15 个典型对象 (局部变量、全局变量、static 变量、malloc 内存、函数代码、字符串字面量、返回地址、参数…) 完成归类练习,全部正确。
输入与输出
无程序输入输出。交付物:①速查卡(手写/电子均可);②15 个对象的归类表与理由。
功能要求
- 五区完整:代码区、常量区、全局/静态区、堆区、栈区
- 每个对象写出存放区域与理由(生命周期/分配方式)
- 标出栈与堆的增长方向
限制条件
- 纯概念任务,无需编程环境
- 归类理由必须写,不能只填区域名
验收步骤(自检清单 0/4)
验收标准
- 速查卡内容正确完整(验收步骤 1)
- 15 个对象归类全部正确(验收步骤 2)
- 能说明栈是编译期/运行期自动管理、大小受限;堆按需分配但易碎片化(验收步骤 3)
- 能说出 MCU 上少用递归/大数组放静态区或堆(验收步骤 4)
常见失败原因
- 把字符串字面量当成栈变量(字面量在常量区)
- 把 static 局部变量归到栈(static 局部变量在全局/静态区)
- 忘记栈向低地址、堆向高地址增长
可选扩展
- 用一张图画出典型进程内存布局(高地址到低地址:栈→堆→全局区→代码区)
- 预习 1.3.9:malloc 失败会返回什么?
完成必要清单后才能计入"已完成实践"(学习状态自动推导,不提供一键完成)
⑪ 面试问题
面试问题
程序运行时内存分为哪几个区域?分别放什么?高频C/C++ · medium
要点:代码区(指令)、常量区(字符串字面量等)、全局/静态区(.data/.bss)、堆区(动态分配)、栈区(局部变量/调用帧)。
经典五区:代码区(text,只读);常量区(rodata);全局/静态区(已初始化 .data、未初始化 .bss); 堆区(malloc/new,向高地址增长);栈区(局部变量、参数、返回地址,向低地址增长)。 补充:Linux 下可用 size 命令查看各段大小;未初始化全局变量在 .bss,不占文件体积。
追问:- 追问:static 局部变量放哪?(全局/静态区)
- 追问:为什么 .bss 不占可执行文件体积?
评分要点:- 五区齐全
- 每区举例
- 增长方向加分
栈和堆有什么区别?高频C/C++ · medium
要点:栈自动管理、速度快、空间小、连续;堆手动分配、速度慢、空间大、易碎片化。
栈:函数调用自动压栈/弹栈,分配快(移动栈指针),空间通常受限(Linux 默认 8MB 量级, MCU 上可能只有几 KB),生命周期随函数。堆:malloc/new 按需分配,需要手动释放, 管理开销大、易产生碎片与泄漏,但空间大。选型:小对象/临时数据用栈,大块/跨函数生命周期用堆。
追问:- 追问:栈溢出会发生什么?(崩溃/段错误)
- 追问:MCU 上为什么常禁止深递归?
评分要点:- 管理方式
- 速度/空间/碎片
- 生命周期
嵌入式系统中 Flash 和 RAM 各有什么用途?高频嵌入式 · easy
要点:Flash 非易失,存程序与常量;RAM 易失,存运行时变量、栈与堆。
Flash(NOR 为主):掉电保持,容量大,存放固件代码、只读数据;支持片内执行(XIP)。 RAM(SRAM/DRAM):速度快、掉电丢失,存放全局变量、栈、堆与运行期数据。 因此 MCU 选型看 Flash/RAM 配比;程序规模看 Flash,运行期数据量看 RAM——"程序装不下" 和"运行内存不够"是两个不同的资源问题。
追问:- 追问:const 变量一定放在 Flash 吗?(编译期常量可能,运行期 const 不一定)
评分要点:- 非易失/易失区分
- 各自存放内容
- 选型视角加分
⑫ 延伸阅读
- 《深入理解计算机系统(CSAPP)》第 6 章:存储器层次结构;
- GNU binutils 手册:size 命令(查看程序各段大小);
- 维基百科词条:Memory hierarchy(查阅入口);
- 下一章预告:0.1.5 学习方法与课程路线总览——用这张地图安排你的学习计划。
内容来源映射
| 内容部分 | 资料 | 位置 | 标记 | 说明 |
|---|---|---|---|---|
| 存储器层次结构、易失/非易失分类、Flash 分类、内存五区 | 第一阶段讲义 | 8.1/8.2/8.5、10.5 节(PAGE 156-160、176) | 【来源】 | 正文重新组织表述;Cache 与内存类型细节在 7.1 深化 |
| 通俗解释(办公桌-书架-仓库类比)、练习/测验/任务 | 无 | 【补充】 | 全部新编 |