------ 小dora 操作系统学习笔记 Vol.6· 内存管理篇
"dora:为啥我明明有 16GB 内存,程序一运行就报内存不足?"
操作系统无奈一笑: "不是谁都能随便住进我这高级小区。"
🏠 一、内存:程序运行的"别墅区"
我们平时跑一个程序,其实就是在系统内存中分配一块「地皮」,这个过程叫:
内存分配(Memory Allocation)
从操作系统的角度,每一块内存都必须:
- 合理分区,避免冲突
- 控制权限,防止串门
- 高效利用,节约资源
📌 巧记口诀:
"内存是金地,进程是住户。住哪、住多大,全靠系统批地。"
📐 二、进程的内存布局:五大区块
每个用户进程在内存中,拥有独立的虚拟地址空间,通常被分为:
diff
+-------------------------+ ← 高地址
| 栈区 Stack |
| 函数调用临时变量 |
+-------------------------+
| 空闲/保护区 |
+-------------------------+
| 堆区 Heap |
| 动态分配变量 |
+-------------------------+
| 数据段 Data Segment |
| 全局变量 / 静态变量 |
+-------------------------+
| 代码段 Text Segment |
| 可执行指令 |
+-------------------------+ ← 低地址
📌 巧记口诀:
"代码写死,数据靠编,堆向上长,栈向下砍。"
🛠 三、内存分配算法:系统是怎么批地的?
操作系统为了给多个进程合理分配内存,有以下经典分配策略:
1. 首次适应(First Fit)
- 找到第一个能装下内存块的位置就塞
- 简单快速,但容易碎片化
2. 最佳适应(Best Fit)
- 找最接近请求大小的空闲块
- 节省空间,但可能效率低
3. 最差适应(Worst Fit)
- 找最大的空闲块分一部分给你
- 留大块防碎片,但容易浪费
📌 面试记忆口诀:
"首次好找,最佳省地,最差保留大地基。"
🧩 四、内存碎片:空间不是不够,是用得不均
内存碎片分两种:
类型 | 说明 |
---|---|
外部碎片 | 空间足够但不连续 |
内部碎片 | 实际分配大于所需,造成浪费 |
系统通常会通过:
- 紧凑(Compaction)
- 分页(Paging)
- 分段(Segmentation)
来缓解碎片问题。
🧱 五、分页机制:把内存切成小砖块
分页是现代操作系统的核心管理机制,它把虚拟地址分为:
页号(Page Number) + 页内偏移量(Offset)
每个进程看到的是一套独立的虚拟地址空间:
虚拟地址 | 页表 | 物理内存 |
---|---|---|
Page 1 (0x0000) | → Frame 7 | Frame #7 |
Page 2 (0x1000) | → Frame 2 | Frame #2 |
操作系统维护一张**页表(Page Table)**记录页号 → 物理帧的映射。
📌 优点:隔离性好、易于分配、可共享代码段
📌 巧记口诀:
"页表一翻,万象更新,虚实之间系统通灵。"
🧱 六、分段机制:把程序逻辑分区
有些系统采用段式内存管理:将程序划分为代码段、数据段、堆栈段等,每段都有独立的段基址 + 长度。
📌 特点:支持程序结构化访问,适用于模块化程序设计
📌 但:不如分页灵活,易产生外部碎片
🧪 七、段页结合:最强内存组合拳
大部分现代系统采用:
段页式管理(Segmented Paging)
每个段再分页,兼顾结构化与内存利用率。
- 虚拟地址 = 段号 + 页号 + 页内偏移
🚨 八、内存保护机制:防止进程乱串门
操作系统通过:
- 页表权限(读写/只读)
- 地址边界检查
- 用户态 / 内核态隔离
保证每个进程「各住各家,井水不犯河水」。
📌 常见内存错误:
- 段错误(Segmentation Fault)
- 访问非法地址(Null Pointer)
📌 巧记口诀:
"分区保护强,串门要判刑。"
🧪 面试练习题
Q1:一个进程的栈为什么向下增长?
✅ 为了与堆错开方向,避免冲突,提高空间利用率。
Q2:分页机制能解决什么问题?
✅ 内存碎片 / 空间隔离 / 多任务运行。
Q3:虚拟地址是怎么转换成物理地址的?
✅ 通过页表查表,将虚页号映射到物理帧号。
Q4:段页式管理有什么优势?
✅ 可结构化管理 + 减少碎片 + 多级映射更灵活。
✅ 一句话总结
"进程的家不在内存物理地址上,而在操作系统的精心规划中。"