读书笔记
🚥《Operating System:Three Easy Pieces》第二十一章 超越物理内存:机制
00 分钟
2023-1-2
2023-3-28
type
status
date
slug
summary
tags
category
icon
password
Property
Mar 28, 2023 12:55 AM
到目前为止,我们一直假设所有页都常驻在物理内存中。
为了支持更大的地址空间,操作系统需要把当前没有在用的那部分地址空间找个地方存储起来。一般来说,这个地方有一个特点,那就是比内存有更大的容量。因此,一般来说也更慢(如果它足够快,我们就可以像使用内存一样使用)。在现代系统中,硬盘(hard disk drive)通常能够满足这个需求。因此,在我们的存储层级结构中,大而慢的硬盘位于底层,内存之上。那么我们的关键问题是:关键问题:如何超越物理内存操作系统如何利用大而慢的设备,透明地提供巨大虚拟地址空间的假象?
内存覆盖(memory overlays):需要程序员根据需要手动移入或移出内存中的代码或数据。设想这样的场景:在调用函数或访问某些数据之前,你需要先安排将代码或数据移入内存。

交换空间

交换空间:在硬盘上开辟一部分空间用于物理页的移入和移出的空间。
操作系统为了能够以页大小为单元读取或者写入交换空间,需要记住给定页的硬盘地址(disk address)。
notion image

存在位

先回想一下内存引用发生了什么。正在运行的进程生成虚拟内存引用(用于获取指令或访问数据),在这种情况下,硬件将其转换为物理地址,再从内存中获取所需数据。
硬件首先从虚拟地址获得 VPN,检查 TLB 是否匹配(TLB 命中),如果命中,则获得最终的物理地址并从内存中取回。这希望是常见情形,因为它很快(不需要额外的内存访问)。
如果在 TLB 中找不到 VPN(即 TLB 未命中),则硬件在内存中查找页表(使用页表基址寄存器),并使用 VPN 查找该页的页表项(PTE)作为索引。如果页有效且存在于物理内存中,则硬件从 PTE 中获得 PFN,将其插入 TLB,并重试该指令,这次产生 TLB 命中。
但是,如果希望允许页交换到硬盘,必须添加更多的机制。具体来说,当硬件在 PTE中查找时,可能发现页不在物理内存中。
硬件(或操作系统,在软件管理 TLB 时)判断是否在内存中的方法,是通过页表项中的一条新信息,即存在位(present bit)。
  • 如果存在位设置为 1,则表示该页存在于物理内存中,并且所有内容都如上所述进行。
  • 如果存在位设置为零,则页不在内存中,而在硬盘上。访问不在物理内存中的页,这种行为通常被称为页错误(page fault)。
在页错误时,操作系统被唤起来处理页错误。一段称为“页错误处理程序(page-fault handler)”的代码会执行,来处理页错误。

页错误

TLB 未命中的情况下,我们有两种类型的系统:
  • 硬件管理的 TLB(硬件在页表中找到需要的转换映射)
  • 软件管理的 TLB(操作系统执行查找过程)。
不论在哪种系统中,如果页不存在,都由操作系统负责处理页错误。操作系统的页错误处理程序(page-fault handler)确定要做什么。几乎所有的系统都在软件中处理页错误。即使是硬件管理的 TLB,硬件也信任操作系统来管理这个重要的任务。
补充:为什么硬件不能处理页错误 我们从 TLB 的经验中得知,硬件设计者不愿意信任操作系统做所有事情。那么为什么他们相信操作系统来处理页错误呢?有几个主要原因。首先,页错误导致的硬盘操作很慢。即使操作系统需要很长时间来处理故障,执行大量的指令,但相比于硬盘操作,这些额外开销是很小的。其次,为了能够处理页故障,硬件必须了解交换空间,如何向硬盘发起 I/O 操作,以及很多它当前所不知道的细节。因此,由于性能和简单的原因,操作系统来处理页错误,即使硬件人员也很开心。
如果一个页不存在,它已被交换到硬盘,在处理页错误的时候,操作系统需要将该页交换到内存中。
操作系统如何知道所需的页在哪儿?在许多系统中,页表是存储这些信息最自然的地方。因此,操作系统可以用 PTE 中的某些位来存储硬盘地址,这些位通常用来存储像页的 PFN 这样的数据。当操作系统接收到页错误时,它会在 PTE 查找地址,并将请求发送到硬盘,将页读取到内存中。
当硬盘 I/O 完成时,操作系统会更新页表,将此页标记为存在,更新页表项(PTE)的PFN 字段以记录新获取页的内存位置,并重试指令。下一次重新访问 TLB 还是未命中,然而这次因为页在内存中,因此会将页表中的地址更新到 TLB 中(也可以在处理页错误时更新 TLB 以避免此步骤)。最后的重试操作会在 TLB 中找到转换映射,从已转换的内存物理地址,获取所需的数据或指令。
请注意,当 I/O 在运行时,进程将处于阻塞(blocked)状态。因此,当页错误正常处理时,操作系统可以自由地运行其他可执行的进程。因为 I/O 操作是昂贵的,一个进程进行I/O(页错误)时会执行另一个进程,这种交叠(overlap)是多道程序系统充分利用硬件的一种方式。

内存满了怎么办

内存可能已满(或接近满了)。因此,操作系统可能希望:
  • 交换出(page out)一个或多个页,以便为操作系统即将交换入的新页留出空间。
  • 从存储交换空间换入(page in)页
选择哪些页被交换出或被替换(replace)的过程,被称为页交换策略(page-replacement policy)。

页错误处理流程

页错误控制流算法(硬件):
页错误处理算法(软件):

交换何时真正发生

为了保证有少量的空闲内存,大多数操作系统会设置高水位线(High Watermark,HW)和低水位线(Low Watermark,LW),来帮助决定何时从内存中清除页。
当操作系统发现有少于 LW 个页可用时,后台负责释放内存的线程会开始运行,直到有 HW 个可用的物理页。这个后台线程有时称为交换守护进程(swap daemon)或页守护进程(page daemon),它然后会进入休眠状态,为操作系统释放了一些内存。 通过同时执行多个交换过程,我们可以进行一些性能优化。例如,许多系统会把多个要写入的页聚集(cluster)或分组(group),同时写入到交换区间,从而提高硬盘的效率,这种合并操作减少了硬盘的寻道和旋转开销,从而显著提高了性能。 为了配合后台的分页线程,
  • 交换算法需要先简单检查是否有空闲页,而不是直接执行替换。
  • 如果没有空闲页,会通知后台分页线程按需要释放页。
  • 当线程释放一定数目的页时,它会重新唤醒原来的线程。
  • 然后就可以把需要的页交换进内存,继续它的工作。

小结

在页表结构中需要添加额外信息,比如增加一个存在位(present bit,或者其他类似机制),告诉我们页是不是在内存中。如果不存在,则操作系统页错误处理程序(page-fault handler)会运行以处理页错误(page fault),从而将需要的页从硬盘读取到内存,可能还需要先换出内存中的一些页,为即将换入的页腾出空间。

参考


评论
Loading...