重要程度:☆☆☆☆

原文:https://skillful-radius-e2d.notion.site/5-6-7-5b1f52cd5637437a9b983e79f31e8572

前情提要:

李无厌:存储器层次结构(一)存储技术概述

李无厌:存储器层次结构(二)Cache 基础知识 - 结构、读写

李无厌:存储器层次结构(三)Cache 的性能评估与改进 — 组相联、全相联、直接映射

Takeaways

虚拟存储:主存(main memory)充当辅存(secondary storage)的 cache

图书馆例子进阶版:

  • 虚拟地址——书名物理地址——书在图书馆中的位置
  • 页表——书名与图书馆位置的关系(图书号)
  • 页号对应地址不在内存中——图书号显示书在另一个图书馆
  • TLB——记录一些书位置的小纸片

TLB 不同,页表不是 cache页表是完备的,因而也不需要标签字段,也不可能同时对所有表项并行比较

一、虚拟机

支持虚拟机的软件被称为虚拟机监视器 (VMM) 或管理程序,VMM 是虚拟机技术的核心。

底层硬件平台被称为主机 (host),它的资源被客户端 (guest) 虚拟机共享。VMM 决定如何将虚拟资源映射到物理资源物理资源可能是分时共享、划分甚至是软件模拟的。

VMM 比传统操作系统小得多,一个 VMM 的隔离区可能只有 10000 行代码。

虚拟机监视器为客户端软件提供软件接口,隔离每个客户端的状态,并且必须保护自己免受客户端软件 (包括客户端操作系统) 的侵害。

如果在设计 ISA 时考虑到虚拟机,减少必须由 VMM 执行的指令数量并提高其仿真速度就相对容易。允许虚拟机直接在硬件上执行的体系结构被冠以_可虚拟化_ 的名称,IBM 370 和 RISC-V 体系结构就是如此。

二、虚拟存储

1. 以页为单位进行访问

主存(main memory)充当辅存(secondary storage)的 cache

提出原因有两点:

  • 为了允许许多虚拟机共享相同的存储(现在的主要动机)
    为了允许多个虚拟机共享内存,必须保护虚拟机免受其他虚拟机影响,确保程序只读写分配给它的那部分主存。主存只需存储众多虚拟机中活跃的部分,就像 cache 只存放一个程序的活跃部分一样。
    我们希望将每个程序都编译到它自己的地址空间中——只有这个程序能访问的一系列存储位置。虚拟存储实现了将程序地址空间转换为物理地址。这种地址转换处理加强了各个程序地址空间之间的保护。

  • 消除小而受限的主存容量对程序设计造成的影响(曾经的主要动机)

在虚拟存储中,地址被划分为虚拟页号页内偏移

页号 - 内存中的页数 页内偏移 - 页大小

  • 虚拟内存中,内存块 (称为)从一组地址 (称为虚拟地址) 映射到另一组(称为物理地址)。
  • 处理器产生虚拟地址,而使用物理地址访问内存。
  • 虚拟页也可能不在主存中,因此不能映射到物理地址(阴影部分);在这种情况下,页被存在磁盘上
  • 物理页也可以被两个指向相同物理地址的虚拟地址共享,用于使两个不同的程序共享数据或代码

拥有比物理页更多数量的虚拟页是一个没有容量限制的虚拟存储的基础。

page fault 问题

缺页失效的高成本是许多设计选择虚拟存储系统的原因。磁盘的缺页失效处理需要数百万个时钟周期。

设计虚拟存储系统时的几个关键决策:

  1. 页应该足够大以分摊长访问时间;
  2. 能降低缺页失效率的组织结构很有吸引力——允许页以全相联方式放置;
  3. 缺页失效可以由软件处理——降低开销,并可以通过算法选择如何放置 page;
  4. 写穿透策略对于虚拟存储不合适二采用写回——写入 storage 的时间实在是太长了。

2. 页的存放与查找——页表

由于缺页失效的代价非常高,设计人员通过优化页的放置来降低缺页失效频率。

允许失效时选择任意一个 page 进行替换——全相联

→全相联项的定位麻烦,cache 中因为块不多还能并行比较,虚拟存储中不可能

→page table

页表虚拟地址与物理地址映射关系的索引表

页表保存在内存中,用虚拟页号来索引,对应项为其对应的物理页号,从而得到物理地址

  • 每个程序都有自己的页表页表是针对程序 / 进程的
  • 页表也可能包含不在内存中的页的表项——valid 指示

为了表明页表在内存中的位置,硬件包含一个指向页表首地址的寄存器,我们称之为页表寄存器。现在假定页表存在存储器中一个固定的连续区域中。

页表指针给出了页表的起始地址。

在该图中,页大小为 个字节,即 4KiB。虚拟地址空间为 字节或 256TiB, 物理地址空间为 字节,主存最大容量为 1TiB。

如果 RISC-V 使用如本图所示的一张页表,则页表中的 entry 数将为 , 即大约 640 亿个 entry。(我们将看到 RISC-V 会尽快减少表项数。)

每个表项的有效位指示映射是否合法

  • valid 为 1,表示 page 在主存中,对应项为物理地址
  • valid 为 0,表示 page 不在主存而在闪存或者磁盘中,对应项为辅存中地址。

由于页表包含了每个可能的虚拟页的映射,因此不需要标签

3. page fault

发生缺页失效

如果虚拟页的有效位为无效,则会发生缺页失效。

操作系统获得控制,这种控制的转移通过 exception 机制完成。一旦操作系统得到控制,它必须在存储层次结构的下一级 (通常是闪存或磁盘) 中找到该页,并确定将请求的页放在主存中的什么位置。

交换区

由于我们无法提前获知存储器中的某一页什么时候将被替换出去,因此操作系统通常会在创建进程时为所有页在闪存或磁盘上创建空间,即 swap space 交换区。(把该进程需要的数据都安排好)

磁盘包含所有页的信息(swap space 交换区),索引方式可以上述同一张页表(valid 为 0 的虚拟页对应项为在磁盘中的位置),也可以另行创建一个数据结构

替换策略

操作系统还会创建一个数据结构用于跟踪记录使用每个物理地址的是哪些进程和哪些虚拟地址。

操作系统遵循最近最少使用 (LRU) 替换策略,查找最近最少使用的页,假定某一页在很长一段时间都没有被访问,那么该页再被访问的可能性比最近经常访问的页的可能性要小,将其替换——写到辅助存储器的交换区。

4.TLB

translation-lookaside buffer,可翻译为快表、转译后备缓冲器、页表缓存转址旁路缓存

用于记录最近发生的地址映射的 cache

结构

  • Dirty:表示该页是否被写过,用于 write-back 操作
  • Ref:在 TLB命中则 ref 置位,LRU 算法会用到
  • Tag:标签项保存虚拟页号的一部分

TLB 作为页表cache用于存放映射到物理页中的那些项

因为 TLBcache,它必须包含标签字段,由于页表包含每个虚拟页的表项,因此不需要标签字段;换句话说,与 TLB 不同,页表不是 cache

流程

每次引用时,在 TLB 中查找虚拟页号。如果命中,则使用物理页号来形成地址,相应的引用位被置位。如果处理器要执行写操作,那么脏位也会被置位

确定是否是真正的 page fault 及处理

  • 如果该页在内存中,TLB 失效表明缺少该地址转换。在这种情况下,处理器可以将 (最后一级) 页表中的地址转换加载到 TLB 中,并重新访问来处理失效。
  • 如果该页不在内存中,那么 TLB 失效意味着真正的缺页失效。在这种情况下,处理器调用操作系统的 exception 处理

由于 TLB 的项数比主存中的页数少得多,TLB 失效比缺页失效更频繁。

三种层次的失效

  • 在最好的情况下,虚拟地址由 TLB 进行转换,然后被送到 cache, 找到相应的数据,取回并发给处理器。
  • 在最坏的情况下,访问在存储层次结构的三个部件中都发生失效:TLB、页表和 cache。

下图显示了所有可能发生的组合以及事实上它们是否真的可能发生。

→还有一种叫做虚拟 cache,即处理器使用完全或部分虚拟的地址来索引 cache。这将 TLB 从关键路径上移开,减少了 cache 的延迟。

处理 TLB 失效和缺页失效(与 Exception 机制的交互)

缺页将在主存访问时钟周期的某一时刻被发现。为了在缺页失效处理结束后重启指令,必须保存导致缺页失效的指令的程序计数器。管理态例外程序计数器 (SEPC) 用于保存该值。

此外,TLB 失效或缺页失效例外必须在访存发生的同一个时钟周期的末尾被判定,这样下一个时钟周期将开始进行例外处理而不是继续正常的指令执行。

一旦操作系统知道引起缺页失效的虚拟地址,它必须完成以下三个步骤:

  1. 使用虚拟地址找到对应的页表表项,并在辅助存储中找到引用页的位置。
  2. 选择要替换的物理页;如果所选页是脏的,则必须先将其写入辅助内存,然后才能将 新的虚拟页写到此物理页中。
  3. 启动读操作,将被访问的页从磁盘上取回到所选择的物理页的位置上。

↑ 读的时间太久,操作系统通常会选择另一个进程在处理器中执行直到磁盘访问结束

当从辅助存储器读页完成后,操作系统可以恢复最初导致缺页失效的进程的状态并执行从例外返回的指令。该指令将处理器从内核态重置为用户态,同时也恢复程序计数器的值。然后,用户进程重新执行引发缺页失效的指令,成功访问所请求的页面,并继续执行。