9.6.1 结合高速缓存和虚拟内存
好的,我们来通过一个具体的例子说明物理寻址和虚拟寻址的 SRAM 高速缓存的区别。
核心概念简述
- 虚拟地址 (Virtual Address, VA):由 CPU 发出的、程序看到的地址。每个进程都有自己独立的虚拟地址空间。
- 物理地址 (Physical Address, PA):在物理内存(DRAM)上的实际地址。整个系统只有一套物理地址空间。
- SRAM 高速缓存:位于 CPU 和主存(DRAM)之间,用于加速内存访问的小而快的存储器。
场景设定
假设我们有两个进程:进程 A 和 进程 B。
它们通过操作系统的内存管理,共享了同一块物理内存页(例如,这是一个共享库的代码段)。具体来说:
- 进程 A 将此共享页映射到其虚拟地址空间的
0x4000处。 - 进程 B 将此共享页映射到其虚拟地址空间的
0x8000处。 - 这块共享内容在物理内存中的实际位置是
0x12345000。
现在,进程 A 和进程 B 都要读取这个共享页开头的一个字(word)data。
例子 1:物理寻址的高速缓存 (Physically Addressed Cache)
这是大多数现代系统的选择(如 x86, ARM)。
工作流程:
-
进程 A 发出读取虚拟地址
VA=0x4000的指令。 -
MMU(内存管理单元) 介入,通过查询进程 A 的页表,将
VA=0x4000翻译成PA=0x12345000。同时,MMU 会检查进程 A 是否有该地址的读取权限(保护机制在此完成)。 -
CPU 现在要获取物理地址
PA=0x12345000的数据。 -
缓存 检查是否存在标签为
0x12345000的数据。我们假设缓存miss,于是从物理内存0x12345000处将data加载到缓存中。缓存的标签是物理地址0x12345000。 -
进程 A 的请求被满足。
-
稍后,进程 B 发出读取虚拟地址
VB=0x8000的指令。 -
MMU 介入,通过查询进程 B 的页表,将
VB=0x8000也翻译成PA=0x12345000(因为它们是共享的同一物理页)。同时检查进程 B 的权限。 -
CPU 现在也要获取物理地址
PA=0x12345000的数据。 -
缓存 再次检查标签
0x12345000,发现缓存命中 (Hit)! 因为之前进程 A 的访问已经把data缓存了。 -
缓存直接将
data返回给 CPU,进程 B 的请求被极大地加速。
物理寻址的优势体现:
- 共享天然高效:尽管进程 A 和 B 使用不同的虚拟地址(
0x4000vs0x8000),但缓存只认最终的物理地址(0x12345000)。数据在缓存中只有一份副本,所有共享该物理页的进程都能受益,缓存利用率高。 - 保护简单:缓存完全不需要关心“当前是哪个进程在访问”或“这个虚拟地址是否有权限”。保护检查由 MMU 在地址翻译阶段统一完成。缓存只是一个“傻傻的”、基于物理地址的快取,设计简单高效。
例子 2:虚拟寻址的高速缓存 (Virtually Addressed Cache)
这种设计较少见,但在一些早期处理器或特定场合(如 TLB 之后的一级指令缓存)存在。
工作流程:
-
进程 A 发出读取虚拟地址
VA=0x4000的指令。 -
CPU 直接使用这个虚拟地址
VA=0x4000去查询缓存(MMU 尚未进行地址翻译)。 -
缓存 检查是否存在标签为
VA=0x4000的数据。假设缓存miss,这时才去启动 MMU 进行地址翻译,得到PA=0x12345000,然后从物理内存加载data。此时,缓存的标签是虚拟地址0x4000。 -
进程 A 的请求被满足。
-
稍后,进程 B 发出读取虚拟地址
VB=0x8000的指令。 -
CPU 直接使用虚拟地址
VB=0x8000去查询缓存。 -
缓存 检查标签
VB=0x8000,发现缓存 miss!因为缓存里存储的是标签为VA=0x4000的数据(进程 A 留下的),虽然它们指向相同的物理数据。 -
于是流程需要从头再来:启动 MMU 翻译
VB=0x8000->PA=0x12345000,然后从内存(或者另一个进程的缓存条目?)加载数据。缓存中现在可能有了两份相同数据的副本,一份标签为0x4000(属于进程 A),另一份标签为0x8000(属于进程 B)。

浙公网安备 33010602011771号