MD 更新:未知

存储管理 · 易错点总结

关联笔记:计算机基础总结存储管理


为什么要分逻辑地址和物理地址?

核心原因:让程序不用关心自己实际放在内存的哪个位置。

没有分离会发生什么?

  • 程序员必须写明变量放在内存第几号位置 → 换台机器就崩
  • 两个程序用了同一个物理地址 → 同时运行互相覆盖

分离后解决了什么问题?

问题解决方案
程序独立性每个程序都从”自己的0地址”开始写,OS 负责映射到真实物理地址
内存保护程序A的逻辑地址0 ≠ 程序B的逻辑地址0,映射到不同物理区域,无法越界
灵活加载物理内存哪里有空洞就映射到哪里,程序不用管
虚拟内存逻辑地址空间可以大于物理内存,暂时不用的页放磁盘,用时调入
共享内存两个进程的逻辑地址映射到同一块物理内存,实现高效通信

类比

逻辑地址 = 酒店房号(每个客人都以为自己是"101号房"的住客)
物理地址 = GPS经纬度(前台知道"101号房"实际对应大楼的哪个物理位置)

换了一个酒店 → 房号还是101 → GPS坐标完全不同
程序也一样,逻辑地址不变,物理地址随加载位置变化

谁来做转换?

MMU(内存管理单元) —— CPU 中的硬件,自动查页表完成逻辑→物理转换,程序无感知。

指针指向的是逻辑地址还是物理地址?

逻辑地址。 用户程序永远接触不到物理地址,从 CPU 执行的第一条指令到最后一个字节,全程经过 MMU 转换:

程序中的指针 → 逻辑地址 ──[MMU]──→ 物理地址 ──→ 实际内存芯片
    ↑                                  ↑
  你能看到的                      硬件自动完成,不可见

直观验证

int a = 42;
int *p = &a;
printf("%p", p);  // 输出如 0x7ffd5c8a1234 → 这是逻辑地址

换个进程跑同样代码,打印出来的地址可能一模一样——因为每个进程有独立的逻辑地址空间,但映射到完全不同的物理位置。

指针不变,物理地址在变

进程A:指针 0x1000 → 逻辑地址 0x1000 ──→ 物理地址 0x8A000
进程B:指针 0x1000 → 逻辑地址 0x1000 ──→ 物理地址 0x3F000
                  ↑ 相同                     ↑ 不同

同一个指针值,换个进程、甚至 OS 把页面 swap 后重新调入,物理地址都可能完全不同——但程序逻辑不受影响,这正是分离的核心价值。


页式存储地址转换

逻辑地址和物理地址的关系

逻辑地址是程序访问时使用的地址,物理地址是数据在内存中的真实地址。

在页式存储中:

逻辑地址 = 页号 × 页面大小 + 页内偏移
物理地址 = 物理块号 × 页面大小 + 页内偏移

转换核心:

页号 -> 查页表 -> 物理块号
页内偏移保持不变

易错点

  • 页面大小为 4K 时,等于 4096B = 1000H
  • 十六进制逻辑地址按 1000H 拆页号和页内偏移
  • 地址转换时只把页号换成物理块号,页内偏移不变

例题

页面大小为 4K,逻辑地址为 1B1AH

1B1AH = 1 × 1000H + B1AH

所以:

页号 = 1
页内偏移 = B1AH

若页表中:

页号 1 -> 物理块号 6

则:

物理地址 = 6 × 1000H + B1AH = 6B1AH

口诀:页号换块号,偏移不变。