物理内存管理

一个编程人员希望拥有容量无限大、速度无限快,而且是非易失型的(nonvolatile)的内存空间,到lab1为止,这个梦想还无法轻易满足。为此绝大多数的计算机采用了一种折衷的方法,即建立一个分层的存储器结构,最高层是CPU内部的一些寄存器,它们的访问速度是最快的,但容量不是很大,一般小于1KB;第二层是高速缓存(即硬件cache),实现在CPU内部,接近寄存器速度,容量一般小于4MB;第三层是主存储器(内存),其访问速度比寄存器小一个数量级、价格便宜,目前几百块人民币就可以买到4GB。以上这三种存储器都是易失型的,即在断电后,其内容全部会丢失掉。第四层是磁盘,它的访问速度较慢、价格较便宜,目前花几百块钱就可以买到存储容量>1TB的硬盘,而且是非易失型的。

操作系统需要尽量满足编程人员的梦想,为此它需要管理上述存储器层次结构形成的存储空间,并完成如下主要任务:

  • 记录存储空间的使用情况,即记录哪些部分正在被使用,哪些部分还空闲;
  • 当需求方需要存储空间时,能快速地分配给它合适大小的空间;在需求方显式表示不需要申请到的存储空间时,能把存储空间回收,便于以后的分配;
  • 隔离不同的内存区域,确保在限制在一个内存区域中运行的软件无法访问区域以外的内存空间。这种机制称为地址保护(地址隔离)机制。
  • 如果内存太小,就需要把内存当中使用较少的数据所占空间送到磁盘上,给使用较多的数据腾出内存空间来;如果将来又访问到缓存到硬盘的数据,需要把这些数据重新加载到内存中进行访问。这种机制称为换入换出(swap in/out)机制,并涉及页替换算法。
  • 即使需求方表明了需要内存,但如果需求方没有实际访问所需内存前,则并不完成实际的物理内存分配。这种机制称为按需分配(如果是基于很分页机制,也称为按需分页)。
  • 设两个具有父子关系的程序共享同一地址空间(子程序同享父程序的地址空间),若二程序只是读此地址空间,则地址空间不会有变化;若其中一个程序对此地址空间某地址进行了写操作,则要把包含此地址的页空间复制一份给执行写操作的程序,这时此二程序将有不同的地址空间,可独立运行,相互不干扰。这种机制减少了父程序创建子程序地址空间的开销,称为写时复制(Copy On Write,简称COW)机制。

本章内容主要涉及操作系统的内存管理,包括物理内存管理和基于分页机制的虚拟内存管理。读者通过阅读本章的内容并动手实践相关的5个project实验:

  • proj5:能够探测物理内存并建立页表,实现分页管理
  • proj5.1/5.1.1/5.1.2:实现基于连续物理页的first/best/worst-fit分配算法
  • proj5.2:实现基于连续物理页的buddy分配算法
  • proj6:实现任意大小内存分配的slab分配算法
  • proj7:实现缺页中断服务例程和虚拟内存管理结构(VMM struct),提供按需分页的支持
  • proj8:实现类似改进时钟算法的页面置换算法并支持页粒度的换入换出机制
  • proj9/proj9.1/proj9.2:完善虚存管理(proj9)并逐步实现了进程间内存共享(proj9.1)和copy on write(COW)机制(proj9.2)

可以掌握如下知识:

  • 与操作系统原理相关
  • 内存管理:基于分页机制的内存管理
  • 内存管理:连续内存分配算法
  • 内存管理:非连续内存分配算法
  • 内存管理和中断:缺页中断服务例程
  • 内存管理:虚存管理中的页面置换算法和页换入换出机制
  • 内存管理:按需分页机制和写时复制机制
  • 操作系统原理之外
  • 80386对分页管理(页表等)的硬件支持
  • 页粒度的页面置换策略和页换入换出的具体实现

本章内容中主要涉及内存管理的重要功能主要有两个:

  • 提供空闲内存空间:这样给操作系统和应用程序的代码和数据足够的存放“地方”,使得二者能够正常高效地运行,为此需要完成内存/外存的空间的分配、管理、释放等算法。
  • 提供内存空间隔离保护:隔离用户态应用程序和内核态操作系统之间,以及不同应用程序之间的内存空间,使得不会出现访问冲突,为此需要为不同的应用程序和操作系统划分不同的地址空间,一个应用程序越界规定的地址空间会出现内存访问故障中断。

为了让读者能够从实践上来理解内存管理的基本原理,我们设计了上述实验,主要的功能逐步实现如下所示:

  • 首先是扩展ucore的功能,使它能够发现并管理PC系统中可用的空闲物理内存;
  • 然后是建立分页机制,建立线性地址(分段机制已经完成了逻辑地址到线性地址的转换)到物理地址的映射关系和具体转换操作,这样使得应用程序无法直接访问到物理地址,而是只能访问由操作系统设定好的物理地址空间,从而使得应用程序的访问空间可控;
  • 为了高效地完成操作系统的其他功能单元和应用程序的空闲内存空间需求,需要设计以页(4096字节)为最小分配单位的面向连续物理地址空间的内存分配算法;
    还要设计面向任意大小的内存空间(在物理地址空间上不一定连续)的虚拟内存分配算法;
  • 为了给应用程序提供超过实际物理内存空间大小的虚拟内存空间,需要把临时不常用到的内存换出(swap out)到硬盘(也称外存)中,等到需要访问的时候,再换入(swap in)到内存中。设计高效的页面置换算法会尽量保存经常访问的数据在内存中,而不经常访问的数据会换出到硬盘中。