简而言之,据我理解,内存管理就是处理器产生虚拟地址。这些地址通过 MMU 使用每个进程的地址表转换为相应的物理地址(必要时,中间使用 TLB 和页面错误)。
我的问题是处理器是否总是产生虚拟地址?就地址空间(用户/内核)、处理器模式(用户/内核)和上下文(进程/系统)而言,处理器何时会产生物理地址?
答案1
假设我们谈论的是 x86/x64:一旦启用分页 - 这是通过设置 CR0 的 PG 位(位 31)来完成的,并且这在启动的早期发生 - 执行代码断言的所有地址,包括代码的地址,都被解释为虚拟地址。
这并不是说处理器生产虚拟地址在某种程度上与产生物理地址有所不同,只是一旦打开该位,就会启用地址转换,从那时起,代码中出来的每个地址都被 MMU 解释为虚拟地址。
用户模式与内核模式无关紧要,进程与系统上下文也无关紧要。所有地址都是虚拟的,并通过页表转换为 RAM(物理)地址。并且页表条目可能将其“页面存在”位清除,这意味着引用将导致页面错误。
我立即想到的只有一种例外:CR3 寄存器包含身体的顶级页表(x64 中的 PML4 表)的地址。当然,操作页表条目等的代码必须处理物理地址。但是,这些物理地址从未被实际断言,从未被运行代码用作提取或存储操作的目标;它们只是被计算、存储和检索。
没有办法“逃避”这种情况并暂时断言物理地址。(如果您确实关闭了 PG 位,则指令流中的下一条指令将不会被执行,除非它的虚拟地址和物理地址恰好相同!对于堆栈指针和代码所需的每个其他保存的地址也有类似的担忧……)
如果需要引用特定的物理地址,则分配一个以前未使用的虚拟页,并设置相应的页表条目以指定所需的物理页号。这就是启用虚拟寻址时驱动程序代码访问 I/O“寄存器”空间的方式。