您在谈论内存虚拟化,除非您正在开发操作系统,否则您不必关心它,因为它对用户进程是透明的。
确实,您的程序看到的地址 notepad.0073053 与处理器硬件地址引脚上的物理地址不同。但是,当处理器执行调用指令时,它不会通过某种魔法转换目标地址,而是将转换后的地址放入程序计数器 - 程序计数器会。通话后,保持 0x007353。
虚拟化是在内存管理单元 (MMU) 中完成的,您可以将其视为实际处理器和内存之间的单独硬件。(当然,它们在现代处理器中位于同一芯片上,但很久以前曾经有单独的 MMU)。可以这样想:
+-----------------+ +----------------------+ +-----------------+
| CPU | | MMU lookup table | | RAM |
+-----------------+ +----------------------+ +-----------------+
| call 73053 | 73053 | virtual | phys. | 63053 |00000 |
| access 73053 on |---------->| 10000-20000 | a0000 |--------->|10000 |
| the address bus | | 40000-50000 | 30000 | |20000 |
+-----------------+ | 70000-80000 | 60000 | |30000 |
+----------------------+ |40000 |
|50000 |
|60000 X |
|70000 |
|80000 |
+-----------------+
MMU 包含一个查找表 - 哪个虚拟地址范围映射到哪个物理地址范围。每当处理器访问内存时,它都会告诉mmu访问哪个虚拟地址;MMU 使用其查找表来确定实际的物理地址,这就是它放在地址总线上的内容。但是,处理器并不关心这种转换。您在 Ollydbg 中看到的始终是虚拟地址,而不是物理地址。
MMU 条目在操作系统内部处理,操作系统可以根据需要重新排列它们。例如,操作系统可能决定需要 60000 处的 RAM 块用于其他用途,将 60000 处的块复制到例如 20000 处,并更新 MMU 表。您的程序不会注意到任何事情 - 它仍然访问相同的虚拟内存位置,该位置现在位于物理内存中的不同位置。
+-----------------+ +----------------------+ +-----------------+
| CPU | | MMU lookup table | | RAM |
+-----------------+ +----------------------+ +-----------------+
| call 73053 | 73053 | virtual | phys. | 23053 |00000 |
| access 73053 on |---------->| 10000-20000 | a0000 |--------->|10000 |
| the address bus | | 40000-50000 | 30000 | |20000 X |
+-----------------+ | 70000-80000 | 20000 | |30000 |
+----------------------+ |40000 |
|50000 |
|60000 |
|70000 |
|80000 |
+-----------------+
如果操作系统决定将内存块分页到磁盘,它将清除相应的 MMU 条目。现在,当处理器尝试访问该虚拟内存时,MMU 将生成一个page fault
,告诉处理器它无法访问该内存。
+-----------------+ +----------------------+ +-----------------+
| CPU | | MMU lookup table | | RAM |
+-----------------+ 73053 +----------------------+ +-----------------+
| call 73053 |---------->| virtual | phys. | |00000 |
| access 73053 on | | 10000-20000 | a0000 | |10000 |
| the address bus | fault! | 40000-50000 | 30000 | |20000 |
+-----------------+<----------| 90000-a0000 | 40000 | |30000 |
+----------------------+ |40000 |
|50000 |
|60000 |
|70000 |
|80000 |
+-----------------+
此页面错误将使处理器调用操作系统内的页面错误处理程序。操作系统保留一个它已写入磁盘的页面的列表,找到当前未使用的内存位置,从磁盘读取所需的页面到该位置,相应地更新 MMU,然后返回到用户程序并重新执行指令产生页面错误。用户程序对此一无所知(除非它努力寻找,例如通过测量所需的实时时间并将其与预期时间进行比较)。在Windows中,perfmon
小号Ram/Page faults per second
柜台将告诉你如何往往是发生了。
(实际上,页面错误有很多种。MMU 表中的空间非常有限,它通常不会映射用户程序的所有虚拟地址。当页面错误发生时,操作系统首先检查“是那块内存吗?在 RAM 某处,只缺少 MMU 条目?”。如果是,操作系统只会生成 MMU 条目并允许程序继续。这称为小页面错误,处理起来非常快;实际访问的页面错误磁盘称为主要页面错误,对性能的影响更大)。