Paging
此篇是在我在OSTEP中看到内存虚拟化分页这一章时所遇到的。需要注意的是,此篇写时我还有点感冒后遗症,脑袋不大清晰,有些地方逻辑会存在混乱,谅解吧。
在看到这篇时,我立刻就回想到了CSAPP中的关于虚拟内存这一块的内容,对比俩本教材,可以明显看到俩种不同的风格,OSTEP是一种很温和的态度来引导你来进行学习,而CSAPP在这时已经进入中间阶段了,一些概念开始成堆的出现了,这个会在一定程度上不利于对于这部分的理解。
分页机制与内存管理
在操作系统的内存管理中,相较于使用分段(Segmentation)作为基本单位,分页(Paging)具有显著的优势。尽管分段可以提供更高的内存管理粒度,但其可变大小的特性导致较高的管理开销。例如,动态分配和回收不同大小的段会引入外部碎片问题,并增加管理的复杂度。因此,分页作为一种固定大小的管理方式,更适合作为内存管理的基本单位。
分页的基本概念
在内存虚拟化过程中,我们希望将内存抽象为一系列可供管理的结构。除了可变大小的段之外,另一种方式是使用固定大小的页(Page)。
分页的核心思想是将整个内存空间划分为大小固定的页,以便进行高效的管理。这种方式具有以下优点:
- 避免外部碎片问题。
- 提供灵活的内存分配策略。
- 便于地址映射和内存保护。
在分页体系中,存在虚拟页(Virtual Page)和物理页(Physical Page)两种概念。
- 物理页:实际存储在RAM或磁盘上的内存块。
- 虚拟页:处于虚拟地址空间中的页,作为进程可见的逻辑地址单元。
操作系统的任务是维护虚拟页与物理页之间的映射关系,从而实现高效的内存管理。
虚拟页到物理页的映射
假设操作系统管理一个64KB的存储空间,并且页大小为16KB,则该存储空间可以划分为4个页框(Frame)。在虚拟内存视角下,这些页框可以被组织成一个页表(Page Table),用于存储页的映射信息。
然而,计算机通常需要同时运行多个进程,每个进程都会拥有独立的虚拟地址空间。这意味着:
- 不同进程的虚拟地址空间在逻辑上是隔离的。
- 但在物理内存中,这些进程的页可能是分散存放的,而不是连续的。
由于物理内存的分配通常是动态的,虚拟页和物理页之间的映射关系并不是固定的。如果直接按照虚拟地址的顺序映射到物理地址,不仅效率低下,还会限制灵活性。因此,我们需要一种机制来管理这种映射关系,使虚拟地址空间能够高效地映射到物理地址空间。
对于一个操作系统(OS)来说,分页相较于分段在内存管理上有其独特的优势。虽然分段能提供更灵活的内存管理,但由于其可变大小的特性,管理上的开销较大。而分页则采用固定大小的内存块,使得管理更加高效。因此,我们重点关注分页机制。
为什么要分页?
在操作系统的内存管理中,我们希望将内存抽象成可管理的单元。除了分段这种可变大小的划分方式,还有一种固定大小的划分方式——页(Page)。页的大小固定,使得整个内存管理更加整齐,减少了碎片化问题,并且让映射管理变得更简单。
在分页系统中,我们主要关注两种页:
- 虚拟页(Virtual Page):进程视角下的逻辑页,操作系统为每个进程维护的抽象地址空间。
- 物理页(Physical Page):实际存储在RAM或磁盘中的内存块,真正承载数据。
但问题来了,如何把一个虚拟页转换到物理页?换句话说,我们如何建立二者之间的映射?
虚拟地址 vs 物理地址
在计算机系统中,我们经常会听到虚拟地址(Virtual Address)和物理地址(Physical Address)这两个概念。
- 虚拟地址:进程使用的地址,提供了一层抽象,使得进程能够独立于物理内存进行访问。例如,在C语言中,使用指针访问变量时,实际上使用的就是虚拟地址。
- 物理地址:数据在硬件中的实际存储地址,是最终被CPU访问的位置。
为了理解它们之间的关系,我们举个例子:
假设一个操作系统管理着64KB的内存,每个页的大小是16KB。这样,总共可以划分出4个页槽位(64KB / 16KB = 4)。在进程的虚拟地址空间中,这些页是连续编号的,但在实际的物理内存中,它们的存放位置可能是离散的。因此,我们需要一种机制来建立映射。
虚拟地址的结构
为了精准地描述一个数据在进程地址空间中的位置,虚拟地址通常由两部分组成:
- 页索引(Page Index):用于标识数据所在的虚拟页。
- 页内偏移(Offset):用于定位数据在该页中的具体位置。
实际上,物理地址的结构也类似,同样由物理页索引和页内偏移构成。由于虚拟页和物理页的大小是相同的,页内偏移部分可以直接复用,这让地址转换的计算更加简单。
所以,虚拟地址到物理地址的转换,关键在于虚拟页索引到物理页索引的映射,而页内偏移部分保持不变。
小结
分页机制的核心思想是:
- 通过固定大小的页管理内存,使得内存分配更加高效。
- 虚拟地址由页索引和页内偏移组成,物理地址的结构类似。
- 虚拟地址到物理地址的转换,主要依赖页索引之间的映射,而页内偏移保持不变。
页表
在之前的内容中,我们已经初步了解了虚拟地址到物理地址转换的动机。现在,我们来看看操作系统如何管理这种转换的一种重要机制:页表(Page Table)。
作用
页表的主要作用是提供虚拟地址到物理地址的映射。在分页机制中,虚拟地址被划分为虚拟页号(VPN, Virtual Page Number)**和**页内偏移量**,而物理地址则由物理页号(PPN, Physical Page Number)**和相同的偏移量组成。因此,页表的核心功能是**将虚拟页号映射到物理页号**。
页表项(Page Table Entry, PTE)
页表中的每一个页表项(PTE),需要满足以下基本要求:
- 能够通过虚拟页号索引到正确的页表项
- 在索引到页表项后,能够获取对应的物理页号
除此之外,页表项通常包含一些额外的控制位,用于管理页面的访问权限和状态:
- 有效位(Valid Bit):判断该页是否在主存中,若无效,则需要触发缺页异常(Page Fault)并从磁盘加载该页。
- 读/写/执行权限位:限制对该页的访问权限,如只读、可写、可执行等。
- 缓存控制位:决定该页是否允许被 CPU 缓存,用于管理 I/O 设备映射等。
- 脏位(Dirty Bit):指示该页是否被修改过,若为1,则需要在换出时写回磁盘。