Appearance
运行时内存映像与地址空间
考情分析
逻辑地址与物理地址的概念是后续内存管理章节的基础,内存映像结构偶有考查。🔥 低频但基础。
程序里写的地址是 0x0040,物理内存的 0x0040 可能已经被别的进程占了——谁来保证每个进程都觉得自己独占了一整块内存?
逻辑地址 vs 物理地址
| 概念 | 说明 |
|---|---|
| 逻辑地址(虚拟地址) | CPU 生成的地址,程序中使用的地址 |
| 物理地址 | 内存单元的真实地址,内存芯片上的地址 |
| 地址空间 | 逻辑地址的集合称为逻辑地址空间,物理地址的集合称为物理地址空间 |
用户程序只能看到逻辑地址,物理地址对用户是透明的——就像你在商场里看到的是"3 楼 A 区 12 号店铺"(逻辑地址),而不需要知道这个店铺在整栋大楼里的真实坐标(物理地址)。
地址转换
将逻辑地址转换为物理地址的过程叫做地址重定位(Address Relocation),也叫地址映射。
| 方式 | 时机 | 硬件支持 |
|---|---|---|
| 静态重定位 | 装入时 | 无需 |
| 动态重定位 | 运行时 | MMU(内存管理单元) |
现代系统使用 MMU 在运行时完成地址转换:
进程的内存映像
一个进程在内存中的布局(从低地址到高地址):
高地址 ┌─────────────┐
│ 内核空间 │ ← 用户不可访问
├─────────────┤
│ 栈 Stack │ ← 向低地址增长(局部变量、函数调用)
│ ↓ │
│ ... │ ← 空闲区域
│ ↑ │
│ 堆 Heap │ ← 向高地址增长(malloc/new)
├─────────────┤
│ BSS 段 │ ← 未初始化的全局/静态变量
├─────────────┤
│ 数据段 Data │ ← 已初始化的全局/静态变量
├─────────────┤
│ 代码段 Text │ ← 程序指令(只读)
低地址 └─────────────┘各区域的特点
| 区域 | 内容 | 读写权限 | 大小变化 |
|---|---|---|---|
| 代码段 | 机器指令 | 只读 | 固定 |
| 数据段 | 初始化的全局变量 | 可读写 | 固定 |
| BSS 段 | 未初始化的全局变量 | 可读写 | 固定 |
| 堆 | 动态分配的内存 | 可读写 | 向上增长 |
| 栈 | 局部变量、返回地址 | 可读写 | 向下增长 |
堆和栈的区别
| 比较 | 栈 | 堆 |
|---|---|---|
| 管理方式 | 编译器自动管理 | 程序员手动管理 |
| 增长方向 | 高→低 | 低→高 |
| 分配效率 | 快(移动栈指针) | 慢(需要查找空闲块) |
| 典型用途 | 局部变量、函数参数 | malloc/new 分配的对象 |
内存保护
| 方式 | 实现 |
|---|---|
| 上下限寄存器 | 检查物理地址是否在 [下限, 上限] 范围内 |
| 基址 + 界限寄存器 | 检查逻辑地址是否 < 界限寄存器值 |
越界访问会触发地址越界异常,OS 终止违规进程。
考研高频考点
- 🔥🔥 逻辑地址 vs 物理地址的概念
- 🔥🔥 MMU 负责运行时地址转换
- 🔥 进程内存映像的各段含义
- 🔥 堆向上增长、栈向下增长
- 🔥 内存保护的两种方式
了解了单个进程的内存布局,接下来一个更宏观的问题:操作系统本身是怎么组织的?宏内核把所有功能塞进内核态,微内核只保留最小集——下一篇对比各种 OS 结构的设计思路。