虚拟化页表的工作原理

2024-03-19

阅读有关虚拟化页表概念的内容,其中部分页表放入虚拟内存中。维基百科 https://en.wikipedia.org/wiki/Page_table#Virtualized_page_table以及 Patterson 和 Hennessy(页面错误部分中的 5.7 详细阐述)说,您不将entire将页表放入虚拟内存的一个缺点是它会导致循环页错误。但在我看来,还有一个更基本的问题——首先如何找到页表?看来你一定需要some通过定位页表来记录物理内存中开始转换过程的位置。

为了进一步澄清我的问题,我的困惑不是“为什么不能所有页表都在内存中”。相反,这就是给出的理由是为了“防止循环页面错误”。看起来更根本的理由应该是“处理器必须有一些物理地址作为起点”,无论你怎么称呼它,它都是一个物理页表。这与“循环页面错误”有什么关系?看起来更加基本。


The VAX https://en.wikipedia.org/wiki/VAX70年代的架构使用虚拟化线性页表方法来实现分页。 VAX 将 32 位虚拟地址空间划分为四个范围:

  • P0:0x00000000 - 0x3fffffff。
  • P1:0x40000000 - 0x7fffffff。
  • S0:0x80000000 - 0xbffffffff。
  • S1:0xc0000000 - 0xffffffff。

P0(称为程序区域)和P1(称为控制区域)是用户特定的分区,S0是系统(内核)分区,S1是保留的。因此,每个进程都有自己的一组 P0 和 P1 映射,但所有进程和内核共享相同的 S0 映射。

请注意,虚拟地址的最高两个有效位用于确定要访问虚拟内存的哪一部分。每个节(S1 除外,它不可用)都由页表定义。具体来说,P0和P1是由虚拟化页表定义的(页表映射到虚拟内存),但S0的页表没有虚拟化。每个页表都是 4 字节页表条目的连续数组。每个页表条目要么无效,要么有效(这意味着它包含 512 字节页的物理地址)。

VAX提供了6个寄存器来定义页表:一个页表基地址寄存器和一个页表长度寄存器,分别用于虚拟地址空间P0、P1和S0的三个部分。 P0和P1的基地址寄存器包含虚拟地址,其最高两位为10。也就是说,S0的页表包含包含P0和P1的物理地址的页表条目。这使得任何进程的P0和P1的页表都可以驻留在主存或辅助存储器中。另一方面,S0的基地址寄存器包含S0的页表的物理地址。

所以本质上,一个进程的页表被划分为三个连续的页表,其中两个是虚拟化的,一个永远驻留在内存中。从维基百科 https://en.wikipedia.org/wiki/Page_table#Virtualized_page_table:

有人提到创建一个包含以下内容的页表结构 虚拟地址空间中每个虚拟页的映射可能会结束 起来很浪费。但是,我们可以解决过多的空间问题 通过将页表放入虚拟内存中,并让虚拟内存 内存系统管理内存的页表。

然而,该线性页表结构的一部分必须始终保留 驻留在物理内存中,以防止循环页 错误,寻找页表中不存在的关键部分 在页表中,不存在于页表中,等等。

S0 的页表是线性页表的一部分,必须始终驻留在内存中(即,未虚拟化)。但为什么一定要这样呢?如果 S0 的基地址寄存器包含虚拟地址而不是页表的物理地址,会发生什么情况?但那样的话,处理器如何计算出页表的物理基地址呢?我们需要一些具有已知物理地址的附加数据结构,使我们能够找出页表的物理地址。为了便于论证,我们假设我们有一个存储在某处的数据结构。页表是否可以完全换出到辅助存储?是的,如果我们在该数据结构中有“当前位”或“有效位”之类的东西,我们就可以做到这一点。然而,当前位被设置为假,当访问任意虚拟地址的内存时会发生页面错误。操作系统现在需要处理页面错误,如果需要访问任何虚拟地址,它将再次出现页面错误,依此类推。

否则,一般来说,如果页错误处理程序被设计为仅使用指向始终存在的数据和代码的物理地址(通过关闭分页),那么您可以有效地绕过虚拟化整个页表。但这会使处理程序的设计变得相当复杂。

将页表划分为多个连续数组(就像在 VAX 中所做的那样)意味着页表的某些部分(S0)必须始终存在。


但是如果S0的页表包含查找P0和P1的页表的条目,那么这不也是一个有效的多级页表吗?为了回答这个问题,我们来比较一下 VAX 和 32 位 x86 中的地址转换是如何完成的。

在VAX翻译中,虚拟页号与页表索引相同。

|31|29                  9|8       0|
------------------------------------
|  | virtual page number | offset  |
------------------------------------
|  |  page table index   | offset  |
------------------------------------

在 32 位 x86 转换中(禁用 PAE 和 PSE),虚拟页号被划分为两级页表的两个索引。

|31                  12|11        0|
------------------------------------
|  virtual page number |  offset   |
------------------------------------
| PT 1 index|PT 2 index|  offset   |
------------------------------------

在VAX中,只有对用户页表的访问才需要两级查找。更重要的是,这两次查找是使用两个不同的虚拟地址执行的。另一方面,对系统页表的访问仅需要使用单个虚拟地址的单个查找。相比之下,在 x86 中,所有访问都需要使用相同虚拟地址进行两级查找。

x86架构支持虚拟化多级页表。

我们可以设计一个可能比两者都更强大的混合页表。如果我们使用S1分区作为第三个用户分区。我们可以为其表添加一个基地址寄存器,其中包含物理地址而不是虚拟地址(如 P0 和 P1)。通过这种方式,即使是进程也可以获得线性页表的潜在性能优势,同时如果操作系统内存管理器需要,仍然允许虚拟化。但我不知道有任何架构使用过这种设计。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

虚拟化页表的工作原理 的相关文章

  • 变址寻址方式和隐式寻址方式

    索引寻址模式通常用于访问数组 因为数组是连续存储的 我们有一个索引寄存器 它在每次迭代中都会递增 当添加到基地址时 它会给出数组元素地址 我不明白这种寻址模式的实际需要 为什么我们不能通过直接寻址来做到这一点 我们有了基地址 每次访问的时候
  • 如果我的部署目标是8.0,我们是否需要为“armv7”和“arm64”编译iOS应用程序?

    我的应用程序支持iOS8 0及以上版本 而且我知道从iOS7开始它的arm64位架构 在这种情况下 我们是否需要编译 armv7 和 arm64 切片的二进制文件 如果我单独编译arm64 我可以减少我的应用程序大小 这是正确的方法吗 请帮
  • 检测目标 CPU 上的对齐内存要求

    我目前正在尝试构建一个可以在多种机器上运行的代码 从手持口袋和传感器到数据中心的大型服务器 这些架构之间的 许多 差异之一是对齐内存访问的要求 标准 x86 CPU 不需要对齐内存访问 但许多其他 CPU 需要它 如果不遵守规则 就会产生异
  • 哪些标准 C++ 功能可用于查询机器/操作系统架构?

    用于查询运行程序的硬件或操作系统功能的属性的标准 C 功能和实用程序是什么 例如 std thread hardware concurrency 给出机器支持的线程数 但是 如何检测计算机有多少 RAM 或者进程正在使用多少 RAM 或者某
  • cpu 缓存行和预取策略

    我读了这篇文章http igoro com archive gallery of processor cache effects http igoro com archive gallery of processor cache effec
  • 考虑到指令具有不同的长度,CPU 如何知道下一条指令应该读取多少字节?

    所以我正在读一篇论文 其中他们说静态反汇编二进制代码是不可判定的 因为一系列字节可以用多种可能的方式表示 如图所示 其 x86 所以我的问题是 那么CPU是如何执行这个的呢 例如 在图中 当我们到达 C3 之后时 它如何知道下一条指令应该读
  • 了解微架构原因,使更长的代码执行速度提高 4 倍(AMD Zen 2 架构)

    我有以下 C 17 代码 是在 x64 模式下使用 VS 2019 版本 16 8 6 编译的 struct declspec align 16 Vec2f float v 2 struct declspec align 16 Vec4f
  • 为什么 MIPS 中 bgezal 和 bltzal 是基本指令而不是伪指令?

    根据这个MIPS指令参考 http www weblearn hs bremen de risse RST docs MIPS mips isa pdf 有两条指令 bgezal and bltzal 如果分支被采用 则执行相对跳转和链接
  • 包容还是排他? Intel Core IvyBridge 处理器中的 L1、L2 缓存

    我有 Intel Core IvyBridge 处理器 Intel R Core TM i7 3770 CPU 3 40GHz L1 32KB L2 256KB L3 8MB 我知道L3是包容性的 是多核共享的 我想了解有关我的系统的以下信
  • 存储缓冲区是否保存现代 x86 上的物理地址或虚拟地址?

    现代 Intel 和 AMD 芯片大存储缓冲区 https stackoverflow com a 54880249 149138在提交到 L1 缓存之前缓冲存储 从概念上讲 这些条目保存存储数据和存储地址 对于地址部分 这些缓冲区条目是否
  • 虚拟化页表的工作原理

    阅读有关虚拟化页表概念的内容 其中部分页表放入虚拟内存中 维基百科 https en wikipedia org wiki Page table Virtualized page table以及 Patterson 和 Hennessy 页
  • Intel x86 与 AMD x86 CPU 上的访问性能不一致

    我已经实现了一个带有结构内存布局数组的简单线性探测哈希图 该结构包含键 值和指示条目是否有效的标志 默认情况下 该结构体由编译器填充 因为键和值是 64 位整数 但该条目仅占用 8 个布尔值 因此 我也尝试以未对齐访问为代价来打包结构 由于
  • 如何将数据直接写入显存?

    程序员有什么办法可以直接将数据写入显存吗 我知道操作系统对此非常严格 但是某些类型的应用程序 例如视频播放器或电脑游戏 如何将其数据直接写入视频内存 我知道有很多知名的库 例如 OpenGL 但它们毕竟只是普通的库 它们和我和你写的程序没有
  • “机器硬件”和“硬件平台”的区别

    我的 Linux 机器报告 uname a 输出如下 root tom i386 uname a Linux tom 2 6 9 89 ELsmp 1 SMP Mon Apr 20 10 34 33 EDT 2009 i686 i686 i
  • C 易失性变量和高速缓存

    缓存是由缓存硬件对处理器透明地控制的 因此如果我们在C程序中使用易失性变量 如何保证我的程序每次都从指定的实际内存地址读取数据而不是缓存 我的理解是 Volatile 关键字告诉编译器不应优化变量引用 而应按照代码中的编程方式读取变量引用
  • 为什么无法一步读取未对齐的单词?

    鉴于 CPU 的字大小允许它寻址内存中的每个字节 鉴于通过PAE http en wikipedia org wiki Physical address extensionCPU 甚至可以使用比字大小更多的位来进行寻址 CPU 无法一步读取
  • 如何以编程方式获取 vmmap 中显示的信息?

    任何看过 Mark Russovich 演讲 揭示内存管理之谜 的人都知道 vmmap 工具可以向您显示与进程限制 普通 32 位 Windows 上为 2GB 相关的内容 而其他工具似乎很少了解这些内容 我希望能够以编程方式监控我的rea
  • 为什么x86分页没有特权环的概念?

    早在 1982 年 当 Intel 发布 80286 时 他们在分段方案中添加了 4 个特权级别 环 0 3 由全局描述符表 GDT 和局部描述符表 LDT 中的 2 位指定 在 80386 处理器中 Intel 添加了分页功能 但令人惊讶
  • 当我打开在 Xcode 4 中创建的 Google 地图项目时,Xcode 5 会警告我的架构设置

    我刚刚更新到新发布的 Xcode 5 我正在开发一个使用 Google 地图 iOS SDK 的 iOS 应用程序 当我在 Xcode 4 中开发时 我改变了我的Architectures在我的项目设置中进行设置 按照 Google 的步骤
  • CPU是如何做减法的?

    我有一些基本的疑问 但每次我坐下来尝试面试问题时 这些问题和我的疑问就会出现 假设 A 5 B 2 假设A和B都是4字节 那么CPU是怎么做的呢 A B添加 我知道 A 的符号位 MSB 为 0 表示正值 B 的符号位为 1 表示负整数 现

随机推荐