操作系统笔记——内存管理

3. 内存管理

3.1 内存管理基础

3.1.1 内存管理概述

存储器是计算机系统的重要组成部分,是计算机系统中的一种宝贵而紧俏的资源。操作系统中的存储管理是指对内存(又称主存。默认情况下,本章的存储器指的是内存)的管理,是操作系统的重要功能之一

内存管理的功能

  • 内存的分配和回收。由操作系统完成内存空间的分配和管理,使程序设计人员摆脱存储空间分配的麻烦,提高编程效率。为此,系统应记住内存空间的使用情况:实施内存的分配;回收系统或用户释放的内存空间。
  • 地址变换。在多道程序环境下,程序中的逻辑地址与内存中的物理地址通常不一致,因此存储管理必须提供地址变换功能,将逻辑地址转换为物理地址。
  • 扩充内存。借助于虚拟存储技术或其他自动覆盖技术,为用户提供比内存空间大的地址空间,从而实现在逻辑上扩充内存容量的目的。
  • 存储保护。保证进入内存的各道作业都在自己的存储空间内运行,互不干扰。既要防止一道作业因发生错误而破坏其他作业,也要防止其破坏系统程序。这种保护一般由硬件和软件配合完成。

应用程序的编译、链接与装入

应用程序从用户编写的源文件到内存中执行的进程,大致分为 3 个阶段:首先,经过编译程序(Compiler)将源代码编译为若个目标模块 (Object Module);其次,通过链接程序(Linker)将编译好的目标模块以及所需的库函数链接在一起,形成完整的装入模块(LoadModule);最后,通过装入程序(Loader)将这些装入模块装入内存并执行。简单来说,从源程序到执行的进程,经历了编译、链接、装入三个步骤。

在这里插入图片描述

在这里插入图片描述

程序的链接有以下3种方式:

  • 静态链接。在程序运行之前,先把各个目标模块及所需库链接为一个完整的可执行程序,以后不再拆开。
  • 装入时动态链接。将应用程序编译后所得到的一组目标模块装入内存时采用边装入边链接的动态链接方式。
  • 运行时动态链接。直到程序运行过程中需要一些模块时,才对这些模块进行链接。这种链接方式将对某些模块的链接推迟到执行时才进行,也就是说,在执行过程中,当发现一个被调用模块尚未装入内存时,立即去找到该模块并将其装入内存,然后把它链接到调用者模块上。凡在执行过程中未被用到的目标模块,都不会被调入内存和链接到装入模块上,这样不仅可缩短程序的装入过程,而且可节省大量的内存空间,便于修改和更新,便于实现对目标模块的共享。

程序的装入有以下3种方式:

  • 绝对装入。在编译时就知道程序将要驻留在内存的物理地址,编译程序产生含有物理地址的目标代码。这种方式不适合多道程序设计。

  • 可重定位装入。根据内存当前情况,将装入模块装入到内存的适当位置,地址变换通常在装入时一次完成,之后不再改变,这种方式也称为静态重定位。静态重定位的实现很简单,当操作系统为程序分配了一个以某地址为起始地址的连续主存区域后,重定位时将程序中指令或操作数的逻辑地址加上这个起始地址就得到了物理地址。

    在这里插入图片描述

  • 动态运行装入。允许程序运行时在内存中移动位置。装入模块装入到内存后的所有地址都是相对地址,在程序执行过程中,只有当访问到相应指令或数据时,才将要访问的程序或数据的相对地址转换为物理地址。由于重定位过程是在程序执行期间随着指令的执行逐步完成的,因此也称为动态重定位。动态重定位的实现要依靠硬件地址变换机构,最简单的实现方法是利用一个重定位寄存器。当某个作业开始执行时,操作系统负责把该作业在主存中的起始地址送入重定位寄存器中,之后在作业的整个执行过程中,每当访问内存时,系统就会自动将重定位寄存器的内容加到逻辑地址中去,从而得到与该逻辑地址对应的物理地址

    在这里插入图片描述

静态重定位的特点是容易实现,无须增加硬件地址变换机构。但它要求为每个程序分配一个连续的存储区,如果空间不足以放下整个程序就不能分配,而且在程序执行期间不能移动,不能再申请内存空间,难以做到程序和数据的共享。

动态重定位的特点是可以将程序分配到不连续的存储区中,在程序运行之前装入它的部分代码即可投入运行,然后在程序运行期间根据需要动态申请分配内存,便于程序段的共享可以向用户提供一个比主存的存储空间大得多的地址空间。动态重定位需要附加硬件支持,且实现存储管理的软件算法比较复杂。

在重定位中,逻辑地址向物理地址的转化公式为

物理地址=基址寄存器内容+逻辑地址

逻辑地址和物理地址

逻辑地址(Logical Address)是指程序产生的与段(与页关因为只有对用户可见)相关的偏移地址部分源代码在经过编译后,目标程序中所用的地址就是逻辑地址,而逻辑地址的范围就是逻辑地址空间。在编译程序对源代码进行编译时,总是从0号单元开始编址,地址空间中的地址都是相对于0开始的,因此逻辑地址也称为相对地址。在系统中运行的多个进程可能会有相同的逻辑地址,但这些逻辑地址映射到物理地址上时就变为了不同的位置。

物理地址 (Physical Address)是指出现在CPU外部地址总线上的寻物理内存的地址信号,是逻辑地址变换后的最终结果地址,物理地址空间是指内存中物理地址单元的集合。进程在运行过程中需要访问存取指令或数据时,都是根据物理地址从主存中取得。物理地址对于一般的用户来说是完全透明的,用户只需要关心程序的逻辑地址就可以了。从逻辑地址到物理地址的转换过程由硬件自动完成,这个转换过程叫作地址重定位

内存保护

内存保护是为了防止一个作业有意或无意地破坏操作系统或其他作业常用的内存保护方法有界限寄存器方法和存储保护键方法

  • 界限寄存器方法

    采用界限寄存器方法实现内存保护又有上,下界寄存器方法以及基址和限长寄存器方法两种实现方式

    • 上、下界寄存器方法。采用上、下界寄存器分别存放作业的结束地址和开始地址。在作业运行过程中,将每一个访问内存的地址与这两个寄存器中的内容进行比较,如超出范围,则产生保护性中断
    • 基址和限长寄存器方法。采用基址和限长寄存器分别存放作业的起始地址及作业的地址空间长度,基址寄存器也叫重定位寄存器,限长寄存器也叫界地址寄存器。在作业运行过程中,将每一个访问内存的相对地址和重定位寄存器中的值相加,形成作业的物理地址;限长寄存器与相对地址进行比较,若超过了限长寄存器的值,则发出越界中断信号,并停止作业的运行
  • 存储保护键方法

    给每个存储块分配一个单独的保护键,其作用相当于一把“锁”。不同于分区存储块,一个分区由若干存储块组成,每个存储块大小相同,一个分区的大小必须是存储块的整数倍。此外,进入系统的每个作业也被赋予一个保护键,它相当于一把“钥匙”当作业运行时,检查“钥匙”和“锁”是否匹配,如果二者不匹配,则系统发出保护性中断信号,并停止作业的运行

3.1.2 覆盖与交换技术

覆盖技术

覆盖(Overlay)技术主要用在早期的操作系统中,因为在早期的单用户系统中内存的容量一般很小,可用的存储空间受到限制,某些大作业不能一次全部装入内存中,这就产生了大作业与小内存的矛盾,为此引入了覆盖技术。

所谓覆盖技术,就是把一个大的程序划分为一系列覆盖,每个覆盖是一个相对独立的程序单位。把程序执行时并不要求同时装入内存的覆盖组成一组,称为覆盖段;将这个覆盖段分配到同一个存储区域,这个存储区域称为覆盖区,它与覆盖段一一对应。显然,为了使一个覆盖区能被相应覆盖段中的每个覆盖在不同时刻共享,其大小应由覆盖段中的最大覆盖来确定

在这里插入图片描述

A和B模块组成覆盖段1,C、D和E模块组成覆盖段2。为了实现真正覆盖,相应的覆盖区应为每个覆盖段中最大覆盖的大小。采用覆盖技术后,运行该用户程序总共只需80KB的内存。

交换技术

交换(Swapping)是指把暂时不用的某个程序及数据部分(或全部)从内存移到外存中,以便腾出必要的内存空间,或把指定的程序或数据从外存读到相应的内存中,并将控制权转给它,让其在系统上运行的一种内存扩充技术。处理器三级调度中的中级调度就是采用了交换技术。

交换技术的特点是打破了一个程序一旦进入主存便一直运行到结束的限制,但运行的进程大小仍然受实际主存的限制

  • 交换需要备份存储,通常是使用快速磁盘。它必须够大,并且提供对这些内存映像的直接访问。
  • 为了有效使用 CPU,需要每个进程的执行时间比交换时间长,而影响交换时间的素主要是转移时间。
  • 如果换出进程,必须确保该进程完全空闲。
  • 交换空间通常作为磁盘的一整块,且独立于文件系统。
  • 交换通常在有许多进程运行且内存空间紧张时开始启动,而在系统负荷减轻时暂停。
  • 普通的交换使用不多,但交换技术的某些变种在许多系统中(如UNIX 系统)仍发挥着作用。

3.1.3 连续分配管理方式

什么是内部碎片与外部碎片?

根据碎片出现的情况,可以将碎片分为内部碎片和外部碎片。内部碎片是指已经分配给作业但不能被利用的内存空间,外部碎片是指系统中还没有分配给作业,但由于碎片太小而无法分配给申请内存空间的新进程的存储块,如下面讲到的固定分区分配中存在内部碎片,而动态分区分配中存在外部碎片。通俗点理解就是,某个作业所占用的内存区域如果没有装满,就是内部碎片,而作业与作业之间,如果有内存区域没有分配给某个作业,但又不能分配给任何作业,就是外部碎片

单一连续分配

单一连续分配是一种最简单的存储管理方式,通常只能用于单用户、单任务的操作系统中。这种存储管理方式将内存分为两个连续存储区域,其中一个存储区域固定地分配给操作系统使用,通常放在内存低地址部分,另一个存储区域给用户作业使用。通常,用户作业只占用所有分配空间的一部分,剩下一部分实际上浪费掉了

在这里插入图片描述

单一连续分配方式采用静态分配,适合单道程序,可采用覆盖技术。作业一旦进入内存,就要等到其结束后才能释放内存。因此,这种分配方式不支持虚拟存储器的实现,无法实现多道程序共享主存。

单一连续分配方式的优点是管理简单,只需要很少的软件和硬件支持,且便于用户了解和使用,不存在其他用户干扰的问题。其缺点是只能用于单用户、单任务的操作系统,内存中只装入一道作业运行,从而导致各类资源的利用率都很低。单一连续分配会产生内部碎片

固定分区分配

固定分区分配(也称为固定分区存储管理) 方法是最早使用的一种可运行多道程序的存储管理方法,它将内存空间划分为若干个固定大小的分区,每个分区中可以装入一道程序。分区的大小可以不等,但事先必须确定,在运行时不能改变。当有空闲分区时,便从后备队列中选择一个适当大小的作业装入运行。固定分区分配中,程序通常采用静态重定位方式装入内存。为了实现固定分区分配,系统需要建立一张分区说明表,以记录可用于分配的分区号、分区的大小、分区的起始地址及状态,通常按照分区的大小顺序排序。

在这里插入图片描述

当某个用户程序要装入内存时,由内存分配程序检索分区说明表,从表中找出一个能满足要求的尚未分配的分区分配给该程序,然后修改分区说明表中相应分区表项的状态;若找不到大小足够的分区,则拒绝为该程序分配内存。当程序执行完毕不再需要内存资源时,释放程序占用的分区,管理程序只需将对应分区的状态设置为未分配即可。分区的大小可以相等,也可以不相等。

  • 分区的大小相等。缺乏灵活性,造成内存空间的浪费,当程序太大时,一个分区又不足以装入该程序,导致程序无法运行。
  • 分区的大小不相等。可把内存区划分成含有多个较小的分区、适量的中等分区及少量的大分区。可根据程序的大小为之分配适合的分区。

固定分区分配的优点是可用于多道程序系统最简单的存储分配,其缺点是不能实现多进程共享一个主存区,利用率较低,会产生内部碎片

动态分区分配

动态分区分配又称为可变式分区分配,是一种动态划分存储器的分区方法。这种分配方法并不事先将主存划分成一块块的分区,而是在作业进入主存时,根据作业的大小动态地建立分区,并使分区的大小正好满足作业的需要。因此,系统中分区的大小是可变的,分区的数目也是可变的

  • 分区分配中的数据结构

    为了实现动态分区分配,系统中也必须设置相应的数据结构来记录内存的使用情况。常用的数据结构形式如下。

    • 空闲分区表。设置一个空闲分区表来登记系统中的空闲分区,每个空闲分区对应一个表项,每个表项包含分区号、起始地址、大小及状态。

      在这里插入图片描述

    • 空闲分区链。用链头指针将内存中的空闲分区链接起来,构成空闲分区链。图 3-8给出了一个空闲分区链的示例,其实现方法是用每个空闲分区的起始若干个字节存放控制信息,其中存放空闲分区的大小和指向下一个空闲分区的指针

      在这里插入图片描述

  • 分区分配算法

    为了将一个作业装入内存,应按照一定的分配算法从空闲分区表(或空闲分区链)中选出一个满足作业需求的分区分配给作业。如果这个空闲分区的容量比作业请的空间容量要大,那么将该分区的一部分分配给作业,剩下的一部分仍然留在空闲分区表(或空闲分区链)中,同时需要对空闲分区表(或空闲分区链)中的有关信息进行修改

    • 首次适应算法。把空闲分区按照地址递增的次序用链表串成一个队列,每次需要为一个进程分配内存时都从队首开始找,顺着链表直到找到足够大的空闲分区,然后按照作业大小从该分区划出一块内存空间分配给请求者,余下的空闲分区仍然留在空闲分区表(或者空闲分区链)中。若从头到尾都不存在符合条件的分区,则分配失败。
      • 优点:优先利用内存低地址部分的空闲分区,从而保了高地址部分的大的空闲分区,无内部碎片。
      • 缺点:由于低地址部分不断被划分,致使低地址端下许多难以利用的很小的空闲分区(外部碎片),而每次查找又都是从低地址部分开始,这无疑增加了查找可用空闲分区的开销。
    • 下次适应算法。该算法又称为循首次适应算法,即在首次适应算法的基础上把队列改成循环队列(依然是将空闲分区按照地址递增的次序排列),而且也不是每次从队首开始找空闲分区,而是从上次找到的空闲分区的下一个分区开始找
      • 优点:这样使得空闲分区的分布更加均匀,减少了查找空闲分区的开销。
      • 缺点:导致缺乏大的空闲分区。
    • 最佳适应算法。要求将空闲分区按照容量大小递增的次序排列。每次为作业分配内存空间时,总是将能满足空间大小需要的最小的空闲分区分配给作业。这样可以产生最小的内存空闲分区。
      • 优点:这种方法总能分配给作业最恰当的分区,并保留大的分区。
      • 缺点:导致产生很多难以利用的碎片空间。
    • 最差适应算法。要求空闲分区按照容量大小递减的次序排列每次为作业分配内存空间时,总是将满足要求且最大的内存空间分配给作业
      • 优点:这样使分给作业后剩下的空闲分区比较大,足以装入其他作业。
      • 缺点:由于最大的空闲分区总是因首先分配而被划分,当有大作业到来时,其存储空间的申请会得不到满足。
  • 分区的回收

    当作业执行结束时,系统应回收已使用完毕的分区。系统根据回收分区的大小及首地址,在空闲分区表(或空闲分区链)中检查是否有相邻的空闲分区,如有相空闲分区,则合并成一个大的空闲区,并修改有关的分区状态信息。回收分区与已有空闲分区的相邻情况有以下4种:

    在这里插入图片描述

    • 回收区上邻接一个空闲分区,如图 3-9a 所示。此时应将回收区与上邻接分区 F1合并成一个连续的空闲分区。合并分区的首地址为空闲分区 F1 的首地址,其大小为二者之和
    • 回收区下邻接一个空闲分区,如图 3-9b 所示。此时应将回收区与下接分区 F1合并成一个连续的空闲分区。合并分区的首地址为回收区的首地址,其大小为二者之和
    • 回收区上、下各邻接一个空闲分区,如图 3-9c 所示。此时应将回收区与 F1 F2合并为一个连续的空闲分区。合并分区的首地址为 F1 的首地址,其大小为三者之和,且应当把F2从空闲分区表(空闲分区)中删除
    • 回收区不与任何空闲分区相邻接,这时单独建立表项,填写分区大小及地址等信息加入空闲分区表(或空闲分区链)的适当位置,如图 3-9d 所示。
  • 分区分配的动态管理

    在分区存储管理方式中,必须把作业装入到一片连续的内存空间中。如果系统中有若干小的分区,其总容量大于要装入的作业,但由于它们不相邻接,致使作业不能装入内存。例如,内存中有4 个空分区不邻接,它们的大小分别为 20KB、30KB、15KB、25KB,总大小为90KB。但如果有一个40KB 的作业到达,因系统中所有空闲分区的容量均小于40KB故此作业无法装入内存,所以就需要对分区分配进行动态管理。

    • 拼接技术。所谓碎片(也可称为零头),是指内存中无法被用的储空间。在分区存储管理方式下,系统运行一段时间后,内存中的碎片会占据相当数量的空间

      解决碎片问题的方法之一是将存储器中所有已分配分区移动到主存的一端,使本来分散的多个小空闲区连成一个大的空闲区。这种通过移动把多个分散的小分区拼接成一个大分区的方法称为拼接或紧凑,也可称为紧缩

      除了有怎样进行拼接的技术问题外,拼接技术的实现还存在一个拼接时机的问题,这个问题有两种解决方案。

      • 第一种方案是在某个分区回收时立即进行拼接,这样在主存中总是只有一个连续的空闲区。但拼接很费时间,拼接频率过高会使系统开销加大。
      • 第二种方案是当找不到足够大的空闲分区且总容量可以满足作业要求时进行拼接。这样拼接的频率比土一种方案要低得多,但空闲分区的管理要稍微复杂一些。
    • 动态重定位分区分配技术。动态重定位分区分配算法与动态分区分配算法基本相同,两者的差别仅在于:在这种分配算法中增加了拼接功能,通常是在找不到足够大的空闲分区来满足作业要求,而系统中空闲分区容量总和大于作业要求时进行拼接

  • 动态分区分配的优缺点

    • 优点
      • 实现了多道程序共用主存(共用是指多进程同时存在于主存中的不同位置)。
      • 管理方案相对简单,不需要更多开销。
      • 实现存储保护的手段比较简单。
    • 缺点
      • 主存利用不够充分,存在外部碎片。
      • 无法实现多进程共享存储器信息(共享是指多进程都使用同一个主存段)。
      • 无法实现主存的扩充,进程地址空间受实际存储空间的限制。

3.1.4 非连续分配管理方式

非连续分配允许一个程序分散地装入到不相邻的内存分区中。在连续分配管理方式中我们发现,即使内存有超过1GB 的空闲空间,但如果没有连续的 1GB 的空间,需要 1GB 空间的作业仍然是无法运行的:但如果采用非连续分配方式,作业所要求的 1GB 内存空间可以分散地分配在内存的各个区域,当然这也需要额外的空间去存储它们(分散区域)的索引,使得非连续分配方式的存储密度低于连续存储方式

非连续分配管理方式根据分区大小是否固定分为分页存储管理方式和分段存储管理方式,其中分页存储管理方式根据运行作业时是否需要把作业的所有页都装入内存才能运行而分为基本分页存储管理方式和请求分页存储管理方式

基本分页存储管理方式

在分区存储管理中,要求把作业放在一个连续的存储区中,因而会产生碎片问题(外部碎片)。尽管通过拼接技术可以解决碎片问题,但代价较高。如果允许将一个作业存放到许多不相邻接的分区中,那么就可以避免拼接,从而有效地解决外部碎片问题。基于这一思想,引入了分页存储管理(或称页式存储管理) 技术。

  • 分页原理

    在分页存储管理中,用户作业的地址空间被划分成若干个大小相等的区域,称为页或页面。相应地,将主存的存储空间也分成与页面大小相等的区域,称为块或物理块在为作业分配存储空间时,总是以块为单位来分配,可以将作业中的任意一页放到主存的任意一块中

    主存中与页面大小相等的物理块也可称为页框。

    在调度作业运行时,必须将它的所有页面一次调入主存;若主存中没有足够的物理块则作业等待。这种存储管理方式称为简单分页或纯分页。

    页面的大小由机器的地址结构决定。在确定地址结构时,若选择的页面较小,可使页内碎片较小并减少内存碎片的总空间,有利于提高内存利用率,但也会使每个进程要求较多的页面,从而导致页表过长,占用较多内存,还会降低页面换进换出的效率。若选择的页面较大,虽然可以减少页表长度,提高页面换进换出的效率,但却会使页内碎片增大。

    因此,页面的大小应选择适中(通常为 2 的整数幂),以方便地址变换,一般为 512B~4KB。

    分页存储管理系统中的逻辑地址(见图 3-10)含两部分内容:前一部分为页号P,后一部分为页内位移W(也称为页内偏移量)。

    在这里插入图片描述

    上述地址结构中,两部分构成的地址长度为 32位。其中0~11 位是页内位地址,即每页的大小为212B=4KB12~31 位是页号,即一个进程运行的最多页数为220=1M 页

    假设逻辑地址为 A,页面大小为 L,则页号 P= (int)(A/L),页内位 W=A%L。其中“(int)”是强制类型转换为整型,“/”为取商操作,“%”是取余操作。

  • 页表

    为了将逻辑地址上连续的页号映射到物理内存中后成为离散分布的多个物理块,需要将每个页面和每个物理块一一对应,这种映射关系就体现在页表上页表中每个页表项都由页号和块号组成,根据页表项就可以找到每个页号所对应物理内存中物理块的块号。页表通常存放在内存中。

    在这里插入图片描述

    假设一个用户程序在基本分页储管理方式中被分成n页如图3-11a 所示,则其页号与内存中的块号的对应关系如图3-11b 中页表所。根据页表所的对应关系,用户程序的每一页分别存储于图 3-11c 的内存区域中。

  • 基本地址变换机构

    在这里插入图片描述

    整个地址变换过程都是由硬件自动完成的。

    页表寄存器(PTR):用来存放页表在内存中的起始地址和页表的长度

    假设页面大小为L、页表长度为 M、地址为A、地址为 E,下面列出从逻辑地址 A得到物理地址 E访内存的步骤。

    • 计算页号P=(int)(A/L);页内位W=A%L。
    • 比较页号P和页表长度M,若P>=M,则产生越界中断,否则转到3)继续执行。
    • 页表起始地址F与 页号P和页表项长度的乘积相加,用得到的地址值到内存中取出该内存单元存放的数b,这个b就是物理块号。
    • 物理块号b和物理块大小的乘积与页内位移W合成物理地址E。
    • 用得到的物理地址E去访问内存。
  • 具有块表的地址变换机构

    **若页表全部放在主存中,则存取一个数据或一条指令至少要访问两次主存。其中,第一次是通过访问页表以确定所存取的数据或指令的物理地址,第二次是根据所得到的物理地址存取数据或指令。**显然,这种方法比通常执行指令的速度慢了一半。

    为了提高地址变换的速度,可以在地址变换机构中增设一个具有并行查找功能的高速缓冲存储器(又称联想存储器或快表)将部分页表项放在这个高速缓冲存储器中快表(TLB),一般是由半导体存储器实现的,其工作周期与 CPU的周期大致相同,但造价较高。为了降低成本,通常是在快表中存放正在运行作业当前访问的那些页表项,页表的其余部分仍然存放在内存中

    在这里插入图片描述

    • 根据逻辑地址得出页号P与页内位移W
    • 先将页号与快表中的所有页号进行对比,若有匹配的页号,则直接读出对应块号,与页内位移拼接得到物理地址;若没有匹配的页号,则还需访问内存中的页表,从页表中取出物理块号,与页内位移拼接得到物理地址,并将此次的页表项存入快表中。
    • 用得到的物理地址访问内存。由于快表是寄存器,存储空间有限,往往放不了几个页表单元,因此在快表中不一定总能找到所需的页号对应的块号。每次查找页表前都先查找快表,如果找到所需的页号,就直接读出块号,然后只需访问内存一次;如果没有找到所需的页号,那么只能再从页表中找块号,这样就需要访问内存两次,而且比没有快表时增加了访问快表所需的时间。所以要尽量保证快表中放置常用的页号和对应的块号,这样才能真正地做到减少访问时间
  • 两级页表和多级页表

    • 页表大小的计算。在基础分页系统中,页表长度 M 页是由页号的位数决定的。而页表的大小可以理解成一个矩形的面积,这个矩形的长度就是页表长度 M,宽度是每个页表项的大小,即块号的位数。

    • 两级页表。从页表大小的计算公式可知,页表大小和页表长度成正比,而页表长度又随着页号位数的增长而呈指数式增长。所以,如果系统的逻辑地址的位数较多,页表会非常大,而整张页表都需要连续地存放在内存中,这是件很困难的事情,于是就有了两级页表。

      在这里插入图片描述

      两级页表的系统将逻辑地址划分为外层页号、外层页内地址和页内地址先用外层页号 P1在外部页表上查找,找出的单元内容是二级页表的首地址,页表的首地址加上外层页内地址 P2 就是页表项的地址,取出里面的数值(即物理块号),物理块号与页内地址 d 相组合就得到了物理地址。在两级页表机制下,无论是外层页号的位数还是外层页内地址的位数,都比一级页表机制少了很多,这样页表的长度就可以减少很多,相应页表的大小也大大减小了。

    • 多级页表

      对于32位的机器(逻辑地址的位数时32位),采用两级页表机构是合适的,但对于64 位的系统,两级页表机构会使页表的大小变得不可接受,所以可以通过继续增加页表的级数来减小页表的大小,不过会使页表的数量大大增加。多级页表最主要的缺点是要多次访问内存,每次地址变换很浪费时间。

  • 页的共享与保护

    在多道程序系统中,数据的共享是很重要的。在分页存储管理系统中,实现共享的方法是使共享用户地址空间中的页指向相同的物理块

    在分页存储管理系统中实现共享比在分段系统中要困难。因为在分页存储管理系统中,将作业的地址空间划分成页面的做法对用户是透明的,同时作业的地址空间是线性连续的,当系统将作业的地址空间分成大小相同的页面时,被共享的部分不一定被包含在一个完整的页面中,这样不应共享的数据也被共享了,不利于保密。另外,共享部分的起始地址在各作业的地址空间划分成页的过程中,在各自页面中的页内位移可能不同,这也使得共享比较难。

    分页存储管理系统可以为内存提供两种保护方式:

    • 一种是地址越界保护,即通过比较地址变换机构中的页表长度和所要访问的逻辑地址中的页号来完成。
    • 另一种是通过页表中的访问控制信息对内存信息提供保护,例如,在页表中设置一个存取控制字段,根据页面使用情况将该字段定义为读、写、执行等权限,在进行地址变换时,不仅要从页表的相应表目中得到该页对应的块号,同时还要检查本次操作与存取控制字段允许的操作是否相符,若不相符则由硬件捕获并发出保护性中断。
  • 基本分页存储管理方式的优缺点

    • 优点
      • 内存利用率高
      • 实现了离散分配
      • 便于存储访问控制
      • 无外部碎片。
    • 缺点
      • 需要硬件支持(其是快表)
      • 内存访问效率下降
      • 共享困难
      • 有内部碎片

基本分段存储管理方式

分段存储管理相较于分页存储管理有如下优点:

  1. 方便编程:用户把自己的作业按照逻辑关系划分为若干个段,每段都是从0开始编址,有自己的名称和长度
  2. 信息共享,页面是存放信息的物理单位,没有完整的意义;而段是信息的逻辑单位,用户可以把需要共享的部分代码和数据放在同一段以便信息共享。
  3. 信息保护,由于每一段都含相对独立的信息,因此对信息保护可以采取对段进行保护,信息保护相对于分页式方便许多。

  • 分段存储原理

    在分段存储管理系统中,作业的地址空间由若干个逻辑分段组成,每个分段是一组逻辑意义上相对完整的信息集合,每个分段都有自己的名字,每个分段都从0开始编址,并采用一段连续的地址空间。因此,整个作业的地址空间是二维的(段的分类是一维,段内位移是另一维)。分段存储管理中以段为单位分配内存,每段分配一个连续的内存区,但各段之间不要求连续。内存的分配与回收类似于动态分区分配。

    分段存储管理系统的逻辑地址结构由段号 S 和内位 W(也叫段内偏移量)组成

    在这里插入图片描述

    段号S 通常是从0开始的连续正整数。当逻辑地址结构中段号和段内位移占用的位数确定之后,一个作业地址空间中允许的最大段数和各段的最大长度也就确定了。

    例如,在图 3-15中,段号占用的位数为 16 位,段内位移占用的位数也是 16 位,因此一个作最多可以有216=65536段,大段长为64KB。

    分页存储管理系统的地址空间是一维的,而分段存储管理系统是二维的

  • 段表及地址变换过程

    与分页存储管理类似,为了实现从逻辑地址到物理地址的变换,系统为每个进程建立个段表,其中每个表项描述一个分段的信息,表项中包含段号、段长和该段的内存起始地址。

    在这里插入图片描述

    在配置了段表后,执行中的进程可通过查找段表,找到每个段所对应的内存区域,实现从逻辑段到物理内存区的映射

    在这里插入图片描述

    地址变换过程都是由硬件自动完成的

    在这里插入图片描述

    从逻辑地址 A 得到物理地址 E 再访问内存的如下:

    • 从逻辑地址A中取出前几位作为段号S,后几位作为段内位移W
  • 比较段号S 和段表长度M, 若S>=M,则产生越界中断,否则转到3)继续执行

    • 取出段表起始地址 F 和段号 S,使其相加,用得到的地址值到内存中取出该内存单元存放的数。取出来的数的前几位是段长 C,后几位是段的起始地址(基址)b。若段内位移W>=C,则产生越界中断,否则转到 4)继续执行
    • 段的基址b和段内位移W加得到物理地址E。
    • 用到的物理地址E访问内存。
  • 段的共享与保护

    在分段存储管理系统中,分段的共享是通过使多个作业的段表中相应表项都指向被共享段的同一个物理副本来实现的。

    与分页管理类似,分段管理的保护主要有两种:地越界保护和访问控制保护

  • 基本分段存储管理方式的优缺点

    • 优点
      • 便于程序模块化处理和处理变换的数据结构
      • 便于动态链接和共享
      • 无内部碎片。
    • 缺点
      • 与分页类似,需要硬件支持
      • 为满足分段的动态增长和减少外部碎片,要采用拼接技术
      • 分段的最大尺寸受到主存可用空间的限制,有外部碎片。
  • 分段与分页的区别

    分页存储管理与分段存储管理有许多相似之处,例如,两者都采用离散分配方式,且都要通过地址变换机构来实现地址变换。但两者在概念上也有很多区别

    在这里插入图片描述

基本段页式存储管理方式

从上面的介绍中可以看出,分页系统能有效地提高了内存利用率并能解决碎片问题,而分段系统能反映程序的逻辑结构并有利于段的共享。如果将这两种存储管理方式结合起来,就形成了段页式存储管理方式。

在段页式存储管理系统中,作业的地址空间首先被分成若干个逻辑分段,每段都有自己的段号,然后再将每一段分成若干个大小固定的页。对于主存空间的管理仍然和分页管理一样,将其分成若干个和页面大小相同的物理块,对主存的分配以物理块为单位。

段页式存储管理系统的逻辑地址结构包含 3 部分内容:段号S 段内页号P和页内位移D

在这里插入图片描述

为了实现地址变换,段页式存储管理系统中需要同时设立段表和页表。系统为每个进程建立一张段表,而每个分段有一张页表。段表的表项中至少应包括段号、页表始址和页表长度,其中页表始址指出该段的页表在主存中的起始位置;页表的表项中至少应包括页号和块号。此外,为了便于实现地址变换,系统中还需要配置一个段表寄存器,用来存放段表的起始地址和段表长度。

在这里插入图片描述

逻辑地址A得到物理地址E再去访问内存的步骤:

  • 从辑地址中取出前几位为段号S,中间几位为页号P,后几位为页内位移 W
  • 比较段号S 和段表长度M,若 S>M,则产生越界中断,否则转到3)继续执行。
  • 取出段表起始地址 F 与段号 S 相加,用得到的地址值到内存中出该内存单存放的数。取出来的数的前几位是页表长度 C,后几位是页表起始地址 d,若页号P>C,则产生越界中断,否则转到4)继续执行。
  • 页表起始地址d 与页号P和页表项长度的乘积相加得到页表项在内存中的物理地址,查找到该地址存放的数值为物理块号 b。
  • 用物理块号b与页内位W组合成物理地址E
  • 用得到的物理地址E去访问内存。

由上述步骤可知,段页式存储管理系统的地址变换需要访问内存3 次,所以同样可以用高速缓冲寄存器(快表)来减少对内存的访问次数

段页式的确结合了段式和页式的优点,而且克服了段式的外部碎片问题,但是段页式的内部碎片并没有做到和页式一样少。页式存储管理方式下平均一个程序有半页碎片,而段页式存储管理方式下平均一段就有半页碎片,而一个程序往往有很多段,所以平均下来段页式的内部碎片比页式要多

3.2 虚拟内存管理

3.2.1 虚拟内存的基本概念

虚拟内存的引入原因

前面介绍的若干种存储管理方法都是分析如何将多个程序装入内存中并行。这些方法都具有如下两个特点:一次性(作业全部装入内存后才能执行)和驻留性(作业常驻内存直到运行结束)。它们均难以满足较大的作业或者较多的作业进入内存执行。

而程序在执行过程中,有些代码是较少用到的(比如错误处理部分),而且有的程序需要较长时间的 I/O 处理,从而导致了很多内存空间的浪费。为此引入了一种能够让作业部分装入就可以运行的存储管理技术,即虚拟内存管理技术

局部性原理

大多数程序执行时,在一个较短的时间内仅使用程序代码的一部分,相应地,程序所访问的存储空间也局限于某个区域,这就是程序执行的局部性原理。

  • 时间局部性。一条指令的一次执行和下次执行,一个数据的一次访问和下次访问,都集中在一个较短的时期内。
  • 空间局部性。当前指令和邻近的几条指令,当前访问的数据和邻近的数据,都集中在一个较小的区域内。

虚拟内存的定义及特征

基于局部性原理,在程序装入时,一方面可以将程序的一部分放入内存,而将其余部分放在外存,然后启动程序(部分装入)。在程序执行过程中,当所访问的信息不在内存中时,再由操作系统将所需的部分调入内存(请求调入)。另一方面,操作系统将内存中暂时不使用的内容置换到外存上,从而腾出空间存放将要调入内存的信息(置换功能)。从效果上看,计算机系统好像为用户提供了二个存储容量比实际内存大得多的存储器,这种从逻辑上扩充内存容量的存储器系统称为虚拟存储器(简称虚存)

将其称为虚拟存储器是因为这种存储器实际上并不存在,系统只是提供了部分装入、请求调入和置换功能,给用户的感觉是好像存在一个能满足作业地址空间要求的内存。

虚拟内存的意义是让程序存在的地址空间与运行时的存储空间分开,程序员可以完全不考虑实际内存的大小,而在地址空间内编写程序。虚拟存储器的容量由计算机的地址结构决定,并不是无限大。

虚拟内存的特征

  • 离散性。程序在内存中离散存储(离散性并不是虚拟内存的特有特征,基本分页和分段也具有离散性)。
  • 多次性。一个作业可以分成多次调入内存。
  • 对换性(交换性)。作业在运行过程中可以换入、换出。
  • 虚拟性。从逻辑上扩充内存容量,用户可以使用的空间可以远大于实际内存容量。

实现虚拟内存的硬件和软件支持

  • 要有相当数量的外存,足以存放多个用户的程序。
  • 要有一定容量的内存,在处理器上运行的程序必须有一部分信息存放在内存中
  • 中断机构,当用户访问的部分不在内存中时中断程序运行。
  • 地址变换机构,以动态实现虚地址到实地址的地址变换。
  • 相关数据结构,段表或页表。

常用的虚拟存储技术有请求分页存储管理、请求分段存储管理和请求段页式存储管理

3.2.2 请求分页存储管理方式

分页存储管理方式虽然解决了内存中的外部碎片问题,但它要求将作业的所有页面一次性调入主存。当主存可用空间不足或作业太大时,就会限制一些作业进入主存运行。为此引入了请求分页(也称请求页式)存储管理方式,先将程序部分载入内存执行,当需要其他部分时再调入内存。很明显,这种方法是根据程序的局部性原理产生的。

请求分页原理

请求分页存储管理方法在作业地址空间的分页、存储空间的分块等概念上和分页存储管理完全一样。它是在分页存储管理系统的基础上,通过增加请求调页功能、页面置换功能所形成的一种虚拟存储系统。在请求分页存储管理中,作业运行之前,只要将当前需要的一部分页面装入主存,便可以启动作业运行。在作业运行过程中,若所要访问的页面不在主存中,则通过调页功能将其调入,同时还可以通过置换功能将暂时不用的页面置换到外存上,以便腾出内存空间

请求分页=基本分页+请求调页功能+页面置换功能

页面结构

在请求分页系统中使用的主要数据结构仍然是页表,其基本作用是将程序地址空间中的逻辑地址转换成内存空间中的物理地址。由于请求分页系统只将作业的一部分调入内存,还有一部分存放在磁盘上,故需要在页表中增加若干项,以供操作系统在实现页面的调入、换出功能时参考

在这里插入图片描述

  • 页号和物理块号。这两个字段在分页存储管理中已经定义过,是进行地址变换所必需的。
  • 状态位(存在位)。用于判断页面是否在主存中。每当进行主存访问时,根据该位判断要访问的页面是否在主存中,若不在主存中,则产生缺页中断。
  • 访问字段。用于记录页面在一段时间内被访问的次数,或最近已有多久未被访问以供置换算法在选择换出页面时参考。
  • 修改位。用于表示页面调入内存后是否被修改过。当处理器以写方式访问页面时,系统将设置该页面的修改位。由于内存中的页面在外存上都有副本,因此,若页面未被修改则在该页面置换出时不需要将页面写到外存,以减少磁盘写的次数;若页面被修改,则必须将页面重新写到外存上
  • 外存地址。用于指出页面在外存上的存放地址,供调入页面时使用。

缺页中断与地址变换

在请求分页存储管理系统中,若所访问的页面在内存中,其地址变换过程与分页存储管理相同;若访问的页面不在内存,则应先将该页面调入内存,再按照与基本分页存储管理相同的方式进行地址变换。

在这里插入图片描述

若系统发现所要访问的页面不在内存中,便产生一个缺页中断信号,此时用户程序被中断,控制转到操作系统的缺页中断处理程序。缺页中断处理程序根据该页在外存的位置将其调入内存。在调页过程中,若内存中有空闲空间,则缺页中断处理程序只需把缺页装入任何一个空闲存储块中,再对页表中的相应表项进行修改(如填写物理块号、修改状态位、设置访问字段及修改位初值等)即可;若内存中无空闲空间,则必须先淘汰内存中的某些页面,若被淘汰页曾被修改过,则要将其写回外存

缺页中断是一个比较特殊的中断,它与一般中断相比有着明显的区别,主要表现在以下方面:

  • 指令的执行期间产生和处理缺页中断。通常,CPU 是在指令执行完毕后检查是否有中断请求到达,若有,便响应。而缺页中断是在一条指令的执行期间发现要访问的指令和数据不在内存时产生和处理的。
  • 一条指令可以产生多个缺页中断。例如,一条双操作数的指令,每个操作数都不在内存中,则这条指令执行时至少将产生两个缺页中断。

请求分页管理方式的优缺点

  • 优点
    • 可以离散储存程序,降低了碎片数量。
    • 提供虚拟存储器,提高了主存利用率,有利于多道程序运行,方便用户。
  • 缺点
    • 必须有硬件支持。
    • 有些情况下系统会产生抖动现象。
    • 程序最后一页仍然存在未被利用的部分空间。

3.2.3 页面置换算法

页面置换算法(也称为页面淘汰算法) 是用来选择换出页面的算法。在请求页式存储管理方式中,由于一个进程运行时不是所有页面都在内存中,因此会出现缺页中断,若此时内存没有空闲的物理块,就需要置换出内存中的一页,具体置换出哪一页面是由页面置换算法决定的,由此可见,页面置换算法的优劣直接影响系统的效率

  • 页面置换的单位是页面而不是整个进程,交换的单位是整个进程。
  • 当发生缺页中断后,系统不一定会执行页面置换算法。因为发生缺页中断仅仅说明需要执行的页面没有在内存中,如果内存空间中还有空闲块,只需用缺页中断处理程序把需要的页面从外存调入内存即可,不需要页面置换算法;只有在内存中没有空闲块时才需要页面置换算法。所以,缺页中断不一定导致页面置换算法的执行。

最佳置换算法

在预知一个进程的页面号引用串的情况下,每次都淘汰以后不再使用的或以后最迟再被使用的页面,这种算法就是最佳置换算法

显然,最佳置换算法是最优的,具有最低的缺页率。但由于实际操作中往往无法事先知道以后会引用到的所有页面的信息,因此最佳置换算法无法实现,只能作为一个标准来衡量其他置换算法的优劣

在这里插入图片描述

页面顺序:3,4,2,6,4,3,7,4,3,6,3,4,8,4,6

先进先出算法

FIFO算法是最简单的页面置换算法,每次总是淘汰最先进入内存的页面,即淘汰在内存驻留时间最长的页面

该算法实现简单,用一个队列的数据结构就可以实现,将页面按照次序排成一个队列,并设置指针指向最先进入的页面,每次需要淘汰页面时,将指针所指的页面淘汰即可。

不过 FIFO算法可能会产生 Belady 异常(缺页次数随分配的物理块号的增加而增加),这是由于 FIFO 算法忽略了一种现象,就是最早调入的页面往是使用最频繁的页面,因此 FIFO算法与进程实际运行规律不符,可能选择淘汰的页面是程序经常使用的页面,实际效果不好

在这里插入图片描述

最近最少使用算法

选择最近最长时间没有被使用的页面予以淘汰,其思想是用以前的页面引用情况来预测将来会出现的页面引用情况,即假设一个页面刚被访问,那么不久该页面还会被访问。因此最佳置换算法是“向后看”,而最近最少使用法则是“向前看”

该算法可以用寄存器组和栈来实现,性能较好。在常用的页面置换算法中,LRU算法最接近最佳置换算法

在这里插入图片描述

时钟置换算法

时钟置换算法也称为最近未使用(NRU)算法,是 LRU 和 FIFO 的中。作为 LRU 的近似算法,CLOCK 算法给每个页面设置一个访问位,用以标识该页最近有没有被访问过。CLOCK维护一个内存中所有页面的循环链表,当程序需要访问链表中存在的页面时,该页面的访问位就被置位为 1;否则,若程序要访问的页面没有在链表中,那就需要淘汰一个内存中的页面,于是一个指针就从上次被淘汰页面的下一个位置开始顺序地去遍历这个循环链表,当这个指针指向的页面的访问位为 1 时,就把该访问位清零,指针再向下移动,当指针指向的页面的访问位为 0时,就选择淘汰掉这一页面,若遍历了一遍链表仍没找到可以淘汰的页面,则继续遍历下去

在这里插入图片描述

改进型时钟算法

还有一种改进型CLOCK 算法,它考虑了页面载入内存后是否被修改的问题,增加了修改位。在访问位同为 0 的进程间优先淘汰没有修改过的页面,因为没有修改过的页面可以被直接淘汰掉,而修改过的页面需要写回到外存中。与简单 CLOCK 算法相比,该算法可减少磁盘 I/O 次数,但会增加扫描次数。

改进型CLOCK算法增加了修改位后,每个页面的状态存在如下4种情况。

  • 最近未被访问过,也未被修改过(访问位=0,修改位=0)。
  • 最近被访问过,未被修改过(访问位=1,修改位=0)。
  • 最近未被访问,但被修改过(访问位=0,修改位=1)。
  • 最近被访问过,也被修改过(访问位=1,修改位=1)。

改进型时钟算法的算法步骤如下:

  • 从指针的当前位置开始,扫描循环链表。在这次扫描过程中,对访问位和修改位不做修改。选择遇到的第一个(访问位=0,修改位=0)的页面用于替换。
  • 如果第1)步没有找到,重新扫描,寻找(访问位=0,修改位=1)的页面用于替换在这个扫描过程中,每一个非替换的页面都将其访问位置0。
  • 如果第 2)步仍没有找到,则回到起始位置,此时所有页面的访问位均为 0,重新执行第 1) 步和第 2)步,一定能找到替换页面。

其他页面置换算法

  • 最不常用置换(LFU)算法

    选择到当前时间为止访问次数最少的页面淘汰。该算法要求为每页设置一个访问计数器,每当页面被访问时,该页的访问计数器加 1。发生缺页中断时,淘汰计数值最小的页面,并将所有计数器清零

  • 页面缓冲算法

    PBA 算法是对 FIFO 算法的发展,通过建立置换页面的缓冲,找回刚被置换的页面,从而减少系统I/O 的消耗。PBA 算法用 FIFO 算法选择被置换页,选择出的页面不是立即换出而是放入两个链表之一中。如果页面未被修改,就将其归入到空闲页面链表的末尾,否则将其归入到已修改页面链表的末尾。这些空闲页面和已修改页面会在内存中停留一段时间。如果这些页面被再次访问,只需将其从相应链表中移出,就可以返回给进程,从而减少了一次磁盘 I/O。需要调入新的物理页时,将新页面读入到空闲页面链表的第一个页面中,然后将其从该链表中移出。当已修改页达到一定数目后,再将其一起写入磁盘,然后将它们归入空闲页面链表。这样能大大减少 I/O 操作的次数。

3.2.4 工作集与页面分配策略

工作集理论

为了解决抖动现象,引入了工作集的概念。工作集是基于局部性原理假设的。如果能预知程序在某段时间间隔内要访问哪些页面,并能提前将它们调入内存,将会大大降低缺页率,从而减少置换工作,提高 CPU 利用率。

工作集是最近 n 次内存访问的页面的集合,数字n称为工作集窗口,也就是工作集的大小经常被使用的页面会在工作集中,若一个页面不再使用,则它会在工作集中被丢弃。当一个进程寻址一个不在工作集内的页面时,会产生一个缺页中断。在处理缺页中断时,更新工作集并在需要时从磁盘中读入此页面

工作集模型的原理是:让操作系统监视各个进程的工作集,主要是监视各个工作集的大小。若有空闲的物理块,则可以再调一个进程到内存以增加多道的程度;若工作集的大小总和增加超过了所有可用物理块的数量总和,则操作系统可以选择一个内存中的进程对换到磁盘中去,以减少内存中的进程数量来防止抖动的发生。

正确选择工作集窗口大小,即分配给进程的页面数,对存储器的有效利用率和系统吞吐率的提高都将产生重要影响

  • 一方面,若窗口选得很大,进程虽不易产生缺页,但存储器也将不会得到充分利用。
  • 另一方面,若窗口选得过小,则会使进程在运行过程中频繁产生缺页中断,反而降低了系统吞吐率。

页面分配策略

在请求分页存储管理系统中,可以采用两种页面分配策略,即固定分配和可变分配。在进行页面置换时,也可以采用两种策略,即全局置换和局部置换。将它们组合起来,有如下3种适合的策略(固定分配全局置换不合理,因此不存在这种策略)。

  • 固定分配局部置换

    为每个进程分配一定数目的物理块,这个数目是确定的,进程运行期间都不会改变。这样,进程之间不会争夺物理块,会导致有些进程因为物理块太少而频繁地缺页中断,有些进程由于分配的物理块太多而浪费内存空间。采用固定分配局部置换策略时,需要用算法决定每个进程分配多少块物理块,常用的算法有平均分配算法、按比例分配算法以及考虑优先权的分配算法

  • 可变分配全局置换。操作系统维护一个空闲物理块队列,每次有进程缺页时都从空闲物理块队列上取下一个分配给它,如果系统中已经没有空闲的物理块了,那么系统将有可能调出任何进程中的其中一页

  • 可变分配局部置换。为每个进程分配一定量的物理块后,每次发生缺页中断且内存中没有空闲物理块时,只让进程换出自己的某个内存页,但当一个进程频繁地发生缺页中断时,OS 为它分配额外的物理块,直到缺页率降低到合适程度为止,当一个进程缺页率特别低时,则适当减少分配给它的物理块的数量。可变分配局部置换策略在可以获得较高的内存空间利用率的同时,保证每个进程有较低的缺页率

页面调入策略

  • 请求调页策略。一个页面只有在被用到时才被调入到内存中,否则就放在外存中。这种调页方式在一个进程刚启动时会频繁地出现缺页中断,这是因为一开始内存中没有该进程的任何页面。该策略实现简单,但容易产生较多的缺页中断,时间开销大,容易产生抖动现象。
  • 预调页策略。该策略是指将预计不久之后会被用到的页面一并调入到内存,尽管暂时它们还没被用到。在程序启动时,如果程序员能指出哪些页面是首先应该被调入的,并把它们放一起,那么通过预调页策略就可以一次性把它们调入内存,从而可以节省不少时间。这是一种基于局部性原理的预测,通常用于程序的首次调入。

从何处调入页面

请求分页系统中的外存分为两部分:用于存放文件的文件区和用于存放对换页面的对换区。通常,由于对换区是采用连续分配方式,而文件是采用离散分配方式,因此对换区的磁盘 I/O 速度比文件区的高。这样,每当发生缺页请求时,系统应从何处将缺页调入内存。

  • 系统拥有足够的对换区空间。这时可以全部从对换区调入所需页面,以提高调页速度。为此,在进程运行前,便应将与该进程有关的文件从文件区复制到对换区。
  • 系统缺少足够的对换区空间。这时凡是不会被修改的文件,都直接从文件区调入;而当置换出这些页面时,由于它们未被修改而不必再将它们换出,以后再调入时,仍从文件区直接调入。但对于那些可能被修改的部分,在将它们换出时,就应调到对换区,以后需要时再从对换区调入。

3.2.5 抖动现象与缺页率

Belady异常

FIFO置换算法的缺页率可能会随着所分配的物理块数的增加而增加,这种奇怪的现象就是Belady 异常。例如,对于引用串1,2,3,4,1,2,5,1,2,3,4,5,内存中物理块数为3时发生9次缺页中断,而物理块数为4时反倒会发生10 次缺页中断。

产生 Belady 异常的原因是 FIFO算法的置换特征与进程访问内存的动态特征相矛盾,即被置换的页面并不是进程不会访问的

FIFO算法可能出现Belady异常,而 LRU 算法和最佳置换算法永远不会出现 Belady异常,被归类为堆栈算法的页面置换算法也不可能出现 Belady 异常。

抖动现象

若选用的页面置换算法不合适,可能会出现这种现象:刚被淘汰的页面,过后不久又要访问,并且调入不久后又调出,如此反复,使得系统把大部分时间用在了页面的调入调出上.而几乎不能完成任何有效的工作,这种现象称为抖动(或颠簸)

抖动产生的原因是在请求分页系统中的每个进程只能分配到所需全部内存空间的一部分。

缺页率

假定一个作业共有 n页,系统分配给该作业 m页的空间(m<=n)。如果该作业在运行中共需要访问 A 次页面(即引用串长度为 A),其中所要访问的页面不在内存,需要将所需页调入内存的次数为F,则缺页率定义为f=F/A,命中率即为1-f。

缺页率是衡量页面置换算法的重要指标。通常缺页率会受置换算法、分配的页面数量、页面大小等因素的影响。缺页率对于请求分页管理系统是很重要的,如果缺页率过高,会直接导致读取页面的平均时间增加,使进程执行速度显著降低。因此,如何降低缺页率是一项非常重要的工作。

3.2.6 请求分段存储管理系统

请求分段存储管理系统与请求分页存储管理系统一样,为用户提供了一个比主存可用空间大得多的虚拟存储器。同样,虚拟存储器的实际容量由计算机的地址结构确定。在请求分段存储管理系统中,作业运行之前,只要将当前需要的若干段装入主存,便可启动作业运行。在作业运行过程中,若要访问的分段不在主存中,则通过调段功能将其调入,同时还可以通过置换功能将暂时不用的分段置换到外存上,以便腾出内存空间。为此,应对段表进行扩充。

在这里插入图片描述

段号、段长和内存始址这 3 个信息是进行地址变换所必需的,其他字段的含义与请求分页存储管理相同。当段在内存中时,地址变换过程与分段存储管理相同;当段不在内存中时,应先将该段调入内存,然后再进行地址变换

当被访问的段不在主存中时,将产生一个缺段中断信号。操作系统处理该中断时,在主存中查找是否有足够大的分区存放该段。若没有这样的分区,则检查空闲分区容量总和,确定是否需要对分区进行拼接,或者调出一个或几个段后再装入所需段。

猜你喜欢

转载自blog.csdn.net/pipihan21/article/details/129809005