虚拟内存

虚拟内存是一种机制,将连接到 CPU 的物理内存与在 CPU 上执行的所有进程共享。虚拟内存提供了一种保护机制,可以防止其他进程访问分配给特定进程的内存。虚拟内存还提供重定位,即能够在物理内存中的任何位置加载程序而不更改程序中的地址。

在支持虚拟内存的 CPU 中,程序使用虚拟地址进行访问。但是,虽然用户代码在虚拟地址上运行,但从内存中检索数据需要物理地址。此外,为了有效管理稀缺的物理内存,它被划分为页面。因此,应用程序在一组由操作系统提供​​的页面上运行。

访问数据和代码(指令)都需要地址转换。具有 4KB 页面大小的系统的机制如图 @fig:VirtualMem 所示。虚拟地址分为两部分。虚拟页号(52 个最高有效位)用于索引页表,以生成虚拟页号和相应物理页之间的映射。对于 4KB 页面中的偏移量,我们需要 12 位;正如已经说过的那样,64 位指针的其他 52 位用于页本身的地址。请注意,页面内的偏移量(12 个最低有效位)不需要转换,并且“原样”用于访问物理内存位置。

4KB 页面的虚拟到物理地址转换

页表可以是单层或嵌套的。图 @fig:L2PageTables 显示了一个 2 级页表的示例。请注意地址如何分成更多部分。首先要提的是,没有使用 16 个最高有效位。这似乎浪费了位,但即使使用剩余的 48 位,我们也可以寻址 256 TB 的总内存 (2^48^)。一些应用程序使用这些未使用的位来保留元数据,也称为“指针标记”。

2 级页表示例

嵌套页表是一个 radix 树,它与一些元数据一起保存物理页地址。要找到这样一个 2 级页表的翻译,我们首先使用位 32..47 作为索引到 1 级页表,也称为“页表目录”。目录中的每个描述符都指向 2^16^ 个 2 级表块之一。一旦找到合适的 L2 块,我们就使用位 12..31 来找到物理页地址。将其与页偏移量 (位 0..11) 连接起来,我们就得到了物理地址,可以用来从 DRAM 检索数据。

页表的确切格式由 CPU 决定,原因将在接下来的几个段落中讨论。因此,页表组织的变化仅限于 CPU 支持的内容。如今,通常可以看到 4 级和 5 级页表。现代 CPU 支持具有 48 位指针 (256 TB 总内存) 的 4 级页表和具有 57 位指针 (128 PB 总内存) 的 5 级页表。

将页表分为多个级别不会改变可寻址内存的总量。但是,嵌套方法不需要将整个页表存储为连续数组,也不分配没有描述符的块。这节省了内存空间,但增加了遍历页表的开销。

无法提供物理地址映射称为“页面错误”。如果请求的页面无效或当前不在主内存中,就会发生这种情况。两个最常见的原因是:1) 操作系统承诺分配一个页面,但尚未用物理页面支持它,以及 2) 访问的页面被换出到磁盘并且当前没有存储在 RAM 中。

转译后备缓冲区 (TLB)

在分层页表中搜索可能代价高昂,需要遍历层次结构,可能进行多次间接访问。这种遍历通常称为页行走(page walk)。为了减少地址翻译时间,CPU 支持一种称为转译后备缓冲区(translation lookaside buffer, TLB)的硬件结构来缓存最近使用的翻译。类似于普通缓存,TLB 通常设计为 L1 ITLB(指令)、L1 DTLB(数据)的层次结构,然后是共享的 (指令和数据) L2 STLB。为了降低内存访问延迟,TLB 和缓存查找并行发生,因为数据缓存使用虚拟地址操作,不需要预先进行地址翻译。

TLB 层次结构为相对较大的内存空间保留翻译。但是,TLB 未命中可能会非常昂贵。为了加快对 TLB 未命中处理,CPU 具有一个称为硬件页行走器(HW page walker)的机制。这样的单元可以通过发出所需的指令来遍历页表,直接在硬件中执行页行走,而不会中断内核。这就是页表格式由 CPU 决定,操作系统必须遵守的原因。高端处理器有多个硬件页行走器,可以同时处理多个 TLB 未命中。然而,即使使用了现代 CPU 提供的所有加速,TLB 未命中仍然会为许多应用程序造成性能瓶颈。

大页

使用较小的页面大小可以更有效地管理可用内存并减少碎片化。然而,缺点是它需要更多的页表条目来覆盖相同的内存区域。考虑两种页面大小:4KB(x86 上的默认大小)和 2MB 的“大页”大小。对于处理 10MB 数据的应用程序,在第一种情况下需要 2560 个条目,而如果将地址空间映射到巨大页面,只需要 5 个条目。这些在 Linux 上称为“Huge Pages”,FreeBSD 上称为“Super Pages”,Windows 上称为“Large Pages”,但它们都表示同一个意思。在本书的其余部分,我们将它们称为 Huge Pages。

指向 Huge Page 中数据的地址示例如图 @fig:HugePageVirtualAddress 所示。与默认页面大小一样,使用 Huge Pages 时的确切地址格式由硬件决定,但幸运的是,我们作为程序员通常不必担心这一点。

指向 2MB 页面中数据的虚拟地址

使用 Huge Pages 可以大大减少对 TLB 层次结构的压力,因为需要的 TLB 条目更少。它大大增加了 TLB 命中率。我们将在 [sec:secDTLB] 和 [@sec:FeTLB] 中讨论如何使用 Huge Pages 减少 TLB 未命中率。使用 Huge Pages 的缺点是内存碎片化,并且在某些情况下,由于操作系统更难管理大量内存块并确保有效利用可用内存,非确定性页面分配延迟会增加。要在运行时满足 2MB Huge Page 分配请求,操作系统需要找到 2MB 的连续块。如果找不到,操作系统需要重组页面,从而导致更长的分配延迟。

results matching ""

    No results matching ""