地址转换
核心思想: 借鉴CPU虚拟化的受限直接执行 (LDE) 策略,通过硬件辅助的地址转换机制来实现高效、灵活且受控的内存虚拟化。
引言:
- 类比 LDE: 如同CPU虚拟化让大部分指令直接运行,内存虚拟化也希望让程序直接访问内存,但通过硬件和操作系统的协作在每次访问时进行必要的转换和检查。
- 目标:
- 高效 (Efficiency): 利用硬件支持(如寄存器、TLB、页表)减少开销。
- 控制 (Control): 确保应用程序只能访问其自身的内存空间(保护、隔离)。
- 灵活性 (Flexibility): 允许程序方便地使用其地址空间。
- 关键问题: 如何高效、灵活地虚拟化内存,并保持对内存访问的控制?
- 核心技术: 基于硬件的地址转换 (Hardware-based Address Translation)。
- 硬件在每次内存访问时(取指、读数据、写数据)介入。
- 将程序使用的虚拟地址 (Virtual Address) 转换为内存中实际存储位置的物理地址 (Physical Address)。
- 操作系统角色: 管理内存(记录占用与空闲),设置硬件以进行正确的地址转换。
- 最终目的: 创造每个程序拥有私有、连续内存空间的假象 (Illusion),隐藏物理内存被多程序共享的现实。
一、 初始假设 (简化模型)
- 用户地址空间必须连续放置在物理内存中。
- 用户地址空间小于物理内存大小。
- 每个用户地址空间大小相同。 (注:这些假设将在后续章节逐步放宽)
二、 一个地址转换的例子
- 场景: 进程执行
x = x + 3;
- 汇编 (示例):
128: movl 0x0(%ebx), %eax
(从内存加载 x 到 eax)132: addl $0x03, %eax
(加 3)135: movl %eax, 0x0(%ebx)
(写回内存)
- 进程视角 (虚拟地址空间 0-16KB):
- 指令在虚拟地址 128。
- 数据 x 在虚拟地址 15KB。
- 内存访问:取指(128), 加载(15KB), 取指(132), 取指(135), 存储(15KB)。
- 物理内存视角 (进程被重定位到 32KB):
- 操作系统占用 0-16KB。
- 进程地址空间实际位于物理地址 32KB - 48KB。
- 存在空闲内存块。
- 问题: 如何将进程的虚拟地址 (如 128, 15KB) 映射到正确的物理地址 (如 32KB+128, 32KB+15KB),且对进程透明?
三、 机制:动态 (基于硬件的) 重定位
- 也称为:基址加界限 (Base and Bounds) 机制。
- 核心硬件: 每个 CPU 配备两个硬件寄存器:
- 基址寄存器 (Base Register): 存储进程地址空间在物理内存中的起始地址。
- 界限寄存器 (Bounds/Limit Register): 存储进程地址空间的大小 (或结束物理地址)。
- 地址转换过程:
- 程序生成虚拟地址。
- 硬件自动执行:
物理地址 = 虚拟地址 + 基址寄存器值
。 - 硬件同时检查:
0 <= 虚拟地址 < 界限寄存器值
(保护)。 - 如果检查失败 (越界访问),CPU 触发异常 (Exception)。
- 内存管理单元 (MMU): CPU 中负责地址转换和保护检查的硬件部分。
- 优点:
- 透明性: 进程无需知道自己被重定位。
- 保护性: 防止进程访问自身地址空间之外的内存。
- 动态性: 转换在运行时发生,甚至可以在进程运行后移动其地址空间(需OS干预)。
- 对比静态重定位: 静态重定位由加载程序在加载时修改地址,缺乏保护且移动困难。
四、 所需硬件支持
- CPU 模式: 特权模式 (内核模式) 和用户模式。
- 基址/界限寄存器: 每个 CPU 一对,由 MMU 使用。
- 地址转换电路: 执行加法和界限检查。
- 特权指令: 用于操作系统修改基址/界限寄存器 (只能在内核模式执行)。
- 异常机制: CPU 在发生越界访问或用户模式尝试执行特权指令时,能产生异常,并将控制权交给操作系统。
- 异常处理程序注册机制: 操作系统需能告知硬件异常处理程序的位置 (通过特权指令)。
五、 操作系统职责
- 进程创建时:
- 查找空闲物理内存空间 (通常使用空闲列表 Free List 数据结构)。
- 为新进程分配内存,并标记为已用。
- 进程终止时:
- 回收进程占用的物理内存。
- 将回收的空间放回空闲列表。
- 上下文切换时:
- 保存: 将当前进程的基址/界限寄存器值保存到其进程控制块 (PCB)。
- 恢复: 将即将运行进程的基址/界限寄存器值从其 PCB 加载到 CPU 硬件寄存器中。
- 移动进程地址空间 (可选):
- 停止进程 -> 拷贝内存到新位置 -> 更新 PCB 中保存的基址值 -> 恢复运行时加载新基址。
- 异常处理:
- 在启动时设置异常处理程序 (通过特权指令)。
- 当硬件触发异常时 (如越界访问),执行相应的处理程序 (通常是终止违规进程)。
六、 硬件与操作系统交互示例 (时间线)
- OS 启动: 初始化陷阱表、进程表、空闲列表,启动时钟中断。
- 运行进程 A: OS 分配内存、设置基址/界限寄存器 -> 硬件进行地址转换和执行指令。
- 时钟中断/上下文切换: 硬件捕获中断 -> OS 保存 A 的状态 (含基址/界限) -> OS 恢复 B 的状态 (含基址/界限) -> 硬件继续执行 B。
- 进程 B 访问越界: 硬件检查失败,触发异常 -> OS 捕获异常,执行处理程序 (终止 B),回收内存。
- 核心模式: 遵循 LDE,OS 主要在启动、切换、异常时介入,大部分时间由硬件直接执行。
七、 总结与局限性
- 基址加界限 是一种简单、高效的虚拟内存实现机制,提供了地址转换和保护。
- 主要缺点:内部碎片 (Internal Fragmentation)。
- 即使进程实际使用的内存(如栈和堆)远小于分配的固定大小槽块,整个槽块仍被占用。
- 导致物理内存空间浪费,限制了可同时运行的进程数量。
- 下一步: 需要更复杂的机制来更有效地利用物理内存:分段 (Segmentation)。