Skip to content

什么是物理地址,什么是逻辑地址? ​

  • 标签:操作系统

🏛 业务架构师 ​

逻辑地址是程序视角的地址(CPU 产生的虚拟地址),物理地址是内存芯片上的真实地址,两者由 MMU(内存管理单元)+ 页表翻译衔接。

这层翻译带来三个业务系统能够成立的前提:

  • 进程隔离:每个进程有独立地址空间,A 进程拿不到 B 进程的内存——一个服务的内存越界不会踩坏另一个服务,多租户、微服务混合部署的安全性物理上依赖它。没有虚拟地址,任何一个 bug 都可能污染整个机器;
  • 内存超卖与弹性:虚拟地址空间远大于物理内存,按需分配物理页 + swap 兜底——云厂商和容器超卖资源的经济模型建立在这上面。对应到业务运维:K8s 的 memory limit 触发 OOMKilled、机器 swap 导致服务毛刺,根因都在这层翻译;
  • 共享与映射:共享库只载入一份物理内存映射给多个进程;mmap 文件映射让"读大文件"不必整个拷进堆——零拷贝、RocketMQ 的 commitlog 顺序写、页缓存加速,全是 mmap 红利。

与线上排障的直接关联:

  • 进程 RSS 涨但堆内存平稳 → 堆外/直接内存(Netty 场景高频),要看 NMT 与堆外监控而不是 jmap;
  • swap used 上升 → 服务延迟抖动的常见根因,交易类服务直接关 swap;
  • 虚拟内存 vsize 巨大不用慌(JVM 保留地址空间是正常行为),盯 RSS 和物理内存水位。

一句话:这题不是背概念,是理解"进程为什么隔离、容器为什么能超卖、堆外内存去哪了"的底层地图——排障时它决定你往哪看。

🏗 系统架构师 ​

这是操作系统内存管理的核心抽象,我按"为什么需要"讲:

  • 逻辑地址(虚拟地址):程序视角的地址,从 0 或链接基址开始的连续空间,由 CPU 地址总线发出、进程独占;
  • 物理地址:内存芯片上真实单元的地址。

为什么分离:多道程序并发时,若程序直接用物理地址,进程间互相踩踏、恶意进程可读别人数据、程序装载位置必须固定。引入虚拟地址后:每个进程拥有独立、连续、巨大的虚拟地址空间(64 位下 128TB 级),由 MMU + 页表做地址翻译——虚拟页 → 物理帧,隔离(页表权限位 R/W/X)、共享(多进程映射同物理页,共享库)、按需分配(缺页中断才分配物理页,commit 不等于占用)。

关键机制:

  • 多级页表 + TLB 缓存翻译(TLB miss 才走页表遍历);
  • 缺页中断支撑 lazily allocation、swap(页换出到磁盘)、内存映射文件 mmap;
  • 虚拟内存超额分配(overcommit)让进程 RSS 之和可大于物理内存。

架构视角:这是最早的"虚拟化"思想——用一层间接寻址换来隔离、共享与弹性。JVM 堆、容器内存限制、NUMA 亲和、大页(HugePages 降 TLB miss)调优都建立在这套机制上;我做高性能组件时,理解 page fault 与 TLB 的成本,比背参数更能指导优化。

💻 全栈开发专家 ​

逻辑地址(虚拟地址):程序视角的编址,从 0 开始的连续空间,CPU 执行时产生的地址;物理地址:内存芯片上的真实单元编号。两者由 MMU(内存管理单元)+ 页表转换。

text
虚拟地址(48位) → [页目录/页表查表] → 物理页框号 + 页内偏移 → 物理地址
                        ↑
                   TLB 缓存翻译结果(命中免查表)

为什么要这套设计(工程价值):

  1. 进程隔离:每个进程独立虚拟空间,A 绝对摸不到 B 的内存,越界访问直接段错误;
  2. 内存超卖:虚拟空间可以大于物理内存,冷页换出到 swap;
  3. 灵活布局:加载到任意物理位置,共享库映射一份物理页给多进程(.so 的代码段共享);
  4. 权限控制:页表带读/写/执行权限,代码段只读,栈不可执行(防缓冲区溢出的硬件防线)。

和日常工作的连接(这么答加分):

  • OutOfMemoryError: Direct buffer memory 与 NIO 堆外内存;mmap 零拷贝(Kafka/Redis RDB 都用)本质就是"把文件映射进虚拟地址空间";
  • 容器里 free 看到的内存和 JVM 感知的不一致(cgroup 限制的是物理内存,JVM 要用 -XX:+UseContainerSupport);
  • 缺页中断(page fault)高说明内存访问局部性差,性能分析(perf)里能直接看到。