【计算机考研408强化-操作系统】3. 内存管理

3 内存管理

3.1 内存管理概念

为什么要进行内存管理?

页式管理中每个页面表象大小的下限如何决定?

多级页表解决了什么问题?又会带来什么问题?

内存管理的基本原理和要求

操作系统对内存的划分和动态分配,就是内存管理的概念。内存管理的功能

  • 内存空间的分配和回收:由操作系统完成主存储器空间的分配和管理,使程序员摆脱存储分配的麻烦,提高编程效率
  • 地址转换:在多道程序环境下,程序中的逻辑地址与内存中的物理地址不可能一致,因此存储管理必须提供地址变换功能,把逻辑地址转换成相应的物理地址
  • 内存空间的扩充:利用虚拟存储技术和自动覆盖技术,从逻辑上扩充内存
  • 存储保护:保证各道作业在各自的存储空间内运行,互不干扰

程序装入和链接

将用户源程序变为可在内存中执行的程序,通常需要以下几个步骤:

  • 编译。由编译程序将用户源代码(.c)编译成若干目标模块(.o )–>翻译成机器语言或汇编语言

    • 目标模块,又称目标程序,又称为“目的程序”,是源程序被编译后能够被机器直接运行的机器码的集合,在计算机上以.obj作扩展名。由语言程序(编译程序,汇编程序,解释程序)处理成与之等价的机器码构成的,计算机能够直接运行的程序,叫做目标程序。
  • 链接。由链接程序将编译后形成的一组目标模块及所需的库函数链接在一起,形成一个完成的装入模块 --> 也就是形成完整的装入模块

  • 装入。有装入程序将装入模块装入内存内运行

在这里插入图片描述

一些名次的解释

  • 编译。把用高级程序语言编写的程序转换成另一种用低级语言编写的目标程序语言。编译程序属于翻译程序
  • 汇编。
  • 翻译。把一种程序转换成成另一种程序的程序。
  • 解释。解释程序是高级语言翻译程序的一种,他将输入的源程序作为输入,解释一句后就提交给计算机执行一句。就像外语翻译中的口译,说一句就翻译一句,不产生全文的翻译文本。

程序的链接有三种:静态链接、装入时动态链接、运行时动态链接

静态链接

在程序运行之前,先将各目标模块及它们所需的库函数链接成一个完整的可以执行的程序,以后不再拆开(也就是说,链接完再装入模块)

我们通过一个例子来说明在实现静态链接时应解决的一些问题。在图a中示出了经过编译后所得到的三个目标模块A、B、C,它们的长度分别为 L、M和N。在模块A中有一条语句CALL B,用于调用模块B。在模块B中有一条语句CALL C,用于调用模块C。B和C都属于外部调用符号,在将这几个目标模块装配成一个装入模块时,须解决以下两个问题:

(1) 对相对地址进行修改。在由编译程序所产生的所有目标模块中,使用的都是相对地址,其起始地址都为 0,每个模块中的地址都是相对于起始地址计算的。

在链接成一个装入模块后,原模块B和 C在装入模块的起始地址不再是 0,而分别是 L和 L+M,所以此时须修改模块B和C中的相对地址,即把原B中的所有相对地址都加上 L,把原 C中的所有相对地址都加上L+M。

(2) 变换外部调用符号。将每个模块中所用的外部调用符号也都变换为相对地址,如把B 的起始地址变换为 L,把 C 的起始地址变换为 L+M,如图 b所示。

这种先进行链接所形成的一个完整的装入模块,又称为可执行文件。通常都不再拆开它,要运行时可直接将它装入内存。这种事先进行链接,以后不再拆开的链接方式,称为静态链接方式。

在这里插入图片描述

装入时动态链接

装入时动态链接。将用户源程序编译后得到一组目标模块,在装入内存时,采用边装入边链接的方式(边装入边链接)

用户源程序经编译后所得的目标模块,是在装入内存时边装入边链接的,即在装入一个目标模块时,若发生一个外部模块调用事件,将引起装入程序去找出相应的外部目标模块,并将它装入内存,还要按照图4-4所示的方式来修改目标模块中的相对地址。装入时动态链接方式有以下优点:

(1) 、 便于修改和更新。对于经静态链接装配在一起的装入模块,如果要修改或更新其中的某个目标模块,则要求重新打开装入模块。这不仅是低效的,而且有时是不可能的。若采用动态链接方式,由于各目标模块是分开存放的,所以要修改或更新各目标模块是件非常容易的事。

(2)、 便于实现对目标模块的共享。在采用静态链接方式时,每个应用模块都必须含有其目标模块的拷贝,无法实现对目标模块的共享。但采用装入时动态链接方式,OS则很容易将一个目标模块链接到几个应用模块上,实现多个应用程序对该模块的共享。

运行时动态链接

运行时动态链接。对某些目标模块的链接,是在程序中需要该目标模块时才进行的。其优点是便于修改和更新,便于实现对目标模块的共享(先装入,使用时再链接)

装入模块在装入内存时,有三种:绝对装入、可重定位装入、动态运行装入

绝对装入

  • 在编译的时候,如果知道程序将驻留在内存的某个位置,则编译程序将产生绝对地址的目标代码。

  • 绝对装入程序按照装入模块中的地址,将程序和数据装入内存

  • 由于程序中的逻辑地址与实际地址完全相同,故不需对程序和数据的地址进行修改

  • 绝对装入的特点:

    • 绝对装入方式只适用于单道程序环境
    • 程序中所用的绝对地址,可以在编译的时候给出,也可以在汇编的时候给出,也可有程序员直接赋予

可重定位装入

  • 在多道程序下,多个目标模块的起始地址都是从0开始的,程序中的其他地址都是相对于起始地址,此时应该用可重定位装入方式。
  • 根据内存的的当前情况,将装入模块装入内存的适当位置。
  • 静态重定位:装入时对目标程序中指令和数据的修改过程称为重定位,地址变换通常是在装入时一次完成的

在这里插入图片描述

  • 静态重定位的特点是

    • 一个作业装入内存时,必须给它分配要求的全部内存空间,若没有足够的内存,则不能装入作业
    • 作业一旦进入内存,整个运行期间就不能再内存中移动,也不能再申请内存空间

动态运行装入

  • 程序在内存中若发生移动,则需要采用动态的装入方式

  • 装入程序把装入模块装入内存之后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时才进行

  • 在装入内存后的所有地址均为相对地址

  • 这种方式需要一个重定位寄存器的支持

  • 动态运行装入的特点是

    • 可以将程序分配到不连续的存储区
    • 在程序运行之前可以只装入它的部分代码即可投入运行,然后再程序运行期间,根据需要动态申请分配内存
    • 便于程序段共享,可以向用户提供一个比存储空间大得多的地址空间

逻辑地址空间与物理地址空间

  • 逻辑地址。编译后,每个目标模块都从0号单元开始,这称为该目标模块的相对地址(或逻辑地址)。
  • 逻辑地址空间。当链接程序将各个模块链接成一个完整的、可执行目标程序时,链接程序顺序依次按各个模块的相对地址构成统一的从0号单元开始编址。
  • 物理地址。当装入程序将可执行代码装入内存时,必须通过地址转换将逻辑地址转换成物理地址
  • 物理地址空间。内存中物理单元的集合,他是地址转换的最终地址地址,进程在运行时执行指令和访问数据,最后都要通过物理地址从主存中存取。

内存保护

内存保护的两种方法是

  • 在CPU上设置一对上、下限寄存器,存放用户作业在主存中的下限和上限地址,每当CPU要访问一个地址时,分别和两个寄存器的值比较,判断有无越界

  • 采用重定位寄存器(也就是基址寄存器)和界地址寄存器(也就是限长寄存器)来实现这种保护。

    • 重定位寄存器含最小物理地址值,界地址寄存器含逻辑地址的最大值
    • 每个逻辑地址之必须小于界地址寄存器
    • 内存管理机构动态的将逻辑地址与界地址寄存器进行比较,若未发生地址越界,则加上重定位寄存器的值后映射成物理地址,再送交内存单元。

内存保护中注意的点。

  • 重定位寄存器是用来"加"的,逻辑地址加上重定位寄存器中的值就是物理地址
  • 界地址寄存器是用来"比"的,通过比较界地址寄存器中的值与重定位寄存器+逻辑地址的值来判断是否越界。

覆盖

覆盖用来解决程序大小超过物理内存总和的情况

覆盖的基本思路是

  • 由于程序运行时,并非任何时候都要访问程序及数据的各个部分(尤其是一些大型程序)
  • 因此可把用户空间分成一个固定区和若干个覆盖区
  • 经常活跃的部分放在固定区,区域部分按调用关系分段
  • 首先将那些即将要访问的段放入覆盖区,其他段放在外存中,在需要调用前,系统再将其调入覆盖区,替换覆盖区原有的段

覆盖的技术特点是

  • 打破了必须将一个进程的全部信息装入主存后才能运行的限制
  • 但当同时运行程序的代码量大于主存时仍不能运行
  • 内存中能够更新的地方只有覆盖区的段,不在覆盖区的段会常驻内存

覆盖的缺点。

  • 要求给出程序段之间的覆盖结构,使得其对用户和程序员不透明,所以对于主存无法存放用户程序段毛短,现代操作系统是通过虚拟内存来解决的。

交换

交换的基本思想

  • 换出。把处于等待状态(或在CPU调度原则下被剥夺运行权利)段程序从内存移到辅存,把内存空间腾出来
  • 换入。把准备好竞争CPU运行的程序从辅存移到内存

交换要注意的问题

  • 交换需要备份存储,通常是快速磁盘。它必须足够大,并提供对这些内存映像的直接访问
  • 为了有效使用XIIY,需要使每个进程的执行时间比交换时间长,而影响交换时间的主要是转移时间,转移时间与所交换的内存空间成正比
  • 若换出进程,则必须确保该进程完全处于空闲状态
  • 交换空间通常作为磁盘的一个整块,且独立于文件系统,因此使用起来可能很快
  • 交换通常在有许多进程运行且内存空间吃紧时开始启动,而系统负荷降低就暂停
  • 普通的交换使用不多,但交换策略的某些变体在许多系统中仍发挥作用

交换的技术特点

  • 主要在不同进程(或作业)之间进行,而覆盖则用于同一程序或进程中

连续分配管理方式

连续分配方式是指为一个用户程序分配一个连续的内存空间

连续分配管理方式主要有

  • 单一连续分配
  • 固定分区分配
  • 动态分区分配

单一连续分配

单一连续分配是什么

  • 内存在此方式下分为系统区和用户区。系统区仅供操作系统使用,通常在低地址部分;用户区是为用户提供的、出系统区之外的内存空间
  • 这种方式无需进行内存保护,因此内存中永远只有一道程序

单一连续分配的优点

  • 简单
  • 无外部碎片
  • 可采用覆盖技术,不需要额外的技术支持

单一连续分配的缺点

  • 只能用于单用户、单任务的操作系统中
  • 有内部碎片
  • 存储器的利用率极低

固定分区分配

固定分区是什么

  • 是最简单的一种多道程序存储方式,它将用户内存空间划分为若干固定大小的区域,每个分区只装入一道作业
  • 当有空间分区的时候,便可再从外存的后备队列中选择适当大小的作业装入该分区,如此循环

固定分区划分的不同办法是

  • 分区大小相等。用于利用一台计算机去控制多个相同对象的场合,但缺乏灵活性
  • 分区大小不等。划分为多个较少的分区、适量的中等分区和少量的大分区

在这里插入图片描述

固定分区划分的过程

  • 为了便于内存分配,通常将分区按大小进行排序,并为之建立一张分区说明表
  • 分区说明表包括:分区号、大小、起始地址、状态【图】
  • 当用户程序要装入时,便检索该表,如果找到合适的分区就给予分配,并将其状态设置为"已分配"
  • 如果没有找到合适的分区,就拒绝为该用户程序分配内存

固定分区存在的问题

  • 程序可能太大而导致放不进任何一个分区中,这个时候用户就不得不使用【覆盖】技术来使用该内存了
  • 主存利用率低,当程序小于固定分区大小时,也占用一个完成的内存空间,这样分区内部就存在空间碎片,这种现象叫做【内部碎片】

固定分区的优缺点

  • 优点:简单;无外部碎片
  • 缺点:不能实现多进程共享一个主存区,所以存储空间利用率低;有内部碎片

动态分区分配

动态分区是什么

  • 是一种动态划分内存的分区方法。这种分区方法不预先划分内存,而是在进程装入内存时,根据进程的大小动态的建立分区,并使分区的大小正好合适进程需要【图】
  • 系统分区的大小和数目都是可变的

动态分区的缺点和解决办法

  • 动态分区一开始的分配是很好的,但之后回导致内存中出现许多小的内存
  • 随着时间推移,内存中会产生越来越多的碎片,内存的利用率随之下降
  • 这些小的碎片成为【外部碎片】,只在分区外的存储空间会变成越来越多的的碎片,这一点与固定分区中【内部碎片】刚好相对
  • 克服外部碎片的方法是【紧凑】技术来解决,即操作系统不时地对进程进行移动和整理。但这需要动态重定位寄存器的支持,且相对费时

动态分区的算法

首次适应算法

空闲分区以地址递增的次序链接。分配内存是顺序查找,找到第一个大小满足的空闲分区

  • 首次适应算法的优点:简单;最好;最快
  • 首次适应算法的缺点:会使的内存低地址部分出现很多小的空闲分区;每次分配查找时都要经过这些分区,因此增加了查找的开销

在这里插入图片描述

最佳适应算法

  • 空闲分区以容量递增的次序链接,找到第一个大小满足的空闲分区
  • 算法评价:虽然名字是"最佳",但性能最差,因为每次最佳的分配都会留下很小的、难以利用的内存快,会产生最多的外部碎片

在这里插入图片描述

最坏适应算法

  • 空闲分区以容量递减的次序链接,找到第一个大小满足的空闲分区
  • 算法评价:与【最佳适应算法】相反,它选择最大的可用块,这看起来最不容易产生碎片,但是却把最大的连续内存划分开,很快导致没有可用的大内存块,因此性能也非常差

在这里插入图片描述

临近适应算法

  • 由【首次适应算法】演进,不同的是,分配内存时从上次查找结束的位置开始继续查找
  • 算法评价:【邻近最适应算法】是图解决【首次适应算法】从头开始查找的问题,但实际上,他常常导致在内存空位分配空间(因为在一遍扫描中,内存前面部分使用后再释放时,不会参与分配)分裂成小碎片,还不如【首次适应算法】

非连续性分配管理方式

非连续性分配管理方法根据分区的大小是否固定,分为分页存储管理方式和分段存储管理方式

基本分页存储管理方式

固定分区会产生内部碎片,动态分区会产生外部碎片,这两种技术对内存利用率都比较低

引入【分页】思想尽量避免碎片的产生:把主存空间划分为大小相等且固定的块,块相对较小,作为主存的基本单位

每个进程也以块作为单位进行划分,进程执行时,以块为基本单位,逐个申请主存中的块空间

【分页】的方法从形式上来看,像分区相等的【固定分区】技术,分页管理不会产生外部碎片

但它又有本质的区别

  • 块的大小相对分区要小很多
  • 进程也按照块进行划分,进程运行时按块申请主存可用空间并执行

上述这样做的原因是,进程只会在为最后一个不完整的块申请一个主存块空间时,才产生主存碎片,所以尽管会产生内部碎片,内部碎片相对于进程也是很小的。

分页存储的几个基本概念

  • 页面和页面大小。进程中的块称为页,内存中的块称为页框,外存中的块直接被称为块。

    • 【注意】进程在执行时需要申请主存空间,也就是要为每个页面分配主存中的可用页框,这就产生了页和页框的一一对应。

    • 为了方便转换,页面的大小一般来说是2的整数幂,,同时页面大小应该适中。

      • 页面太小会使进程页面过多,这样页表会过长,占用大量内存。
      • 页面太大又会使页内碎片增多,降低内存利用率。
  • 地址结构。页号+业内偏移量

    • 比如,地址长32位,其中0~11位为页内地址,即每页4KB;12~31位为页号,地址空间最多允许2^{20}页

    • 地址结构决定了虚拟内存的寻址空间有多大

在这里插入图片描述

  • 页表。为了便于在内存中找到进程的每个页面所对应的的物理块,操作系统会为每个进程建立一张页表,它记录了页面在内存中对应的物理块号,页表一般存放在内存中。

    • 页表是由【页表项】组成的。
    • 页表项=页号+物理内存中的块号
    • 地址=页号+页内偏移地址
    • 页表项的中的第二部分【物理内存中的块号】+地址中的第二部分【页内偏移地址】=物理地址
    • 在配置页表后,进程执行时,通过查找该表,即可找到每页在内存中的物理块号
    • 页表的作用是实现从页号到物理块号到地址映射

在这里插入图片描述

基本地址变换机构

什么是基本地址变换机构?基本地址变换机构是将逻辑地址转换为内存中的物理地址

在这里插入图片描述

从逻辑地址到物理地址映射过程

  1. 计算页号P(A/L)和页内偏移量W(W=A%L)
  2. 比较页号P和页表长度M,若P>=M,则产生越界中断,否则继续执行。
  3. 页表中的页号P对应的页表项地址=页表始址

基本地址变换机构的特点是要访问两次主存:第一次,是访问主存的页表,确定所取得数据数据或指令的物理地址;第二次是根据该地址去内存中存取数据或指令。

具有快表的地址变换机构

【具有快表的地址变换机构】其实是对【基本地址变换机构】的优化。正如上面介绍基本地址变换机构的特点,需要【访存两次】,这样执行速度就慢下来。于是在地址变换机构中增设一个具有并行查找能力的高速缓冲存储器——【快表(TLB)】,又称【相联存储器】,是通过内【容查】找的存储器(如果学过计算机组成原理的小伙伴一定还记得虚拟存储器中的快表吧),用来存放当前访问的若干页表项,以加速地址变换过程,与此对应的是主存中的页表,被称为【慢表】。

在这里插入图片描述

在具有快表的分页机制中,地址的变换过程如下:

  1. CPU给出逻辑地址后,由硬件进行地址转换,将叶号送入高速缓存寄存器,并将此页号与快表中的所有页号进行比较
  2. 若找到匹配的页号,说明所要访问的页表项在快表中,则直接从中取出该页对应的页框号,与页内偏移量拼接形成物理地址,这样存储数据仅一次访存即可
  3. 若未找到,需要访问主存中的页表,在独处也表项后,应同时将其存入快表,以便后面可能的再次访问。若快表已满,则必须按照一定的算法对旧的页表项进行替换。

两级页表:一级页号+二级页号+页内偏移

在这里插入图片描述

以32位逻辑地址空间、页面大小4KB、页表项大小4B为例,若要实现进程对全部逻辑地址的映射,则每个进程需要2^20个页表项,也就是说,仅仅保存页表项就需要4MB的存储空间,这显然是不合适的。

为了压缩页表,计算机科学家进一步延伸页表映射思想,就得到了二级分页。为了查询方便,顶级页表最多只能有一个页面,因此顶级页表总共可以容纳4KB/4B=1K个页表项。注意,1K个页表项占用的地址位数是10位,页面带奥4KB也就是12位,因此一个32位的逻辑地址空间就剩下了10位,正好使得二级页表的大小在一页之内。

在这里插入图片描述

如何解决单级页表问题?

问题一:页表必须连续存放,因此,当页表很大时,需要占用很多个连续的页框,违背了离散原则

问题二:没有必要让整个页表常驻内存,因为进程在一段时间内可能只需要访问某几个特定页面

解决方法:可将长长的页表分组,使每个内存块刚好可以放入一个分组。另外,要为离散分配的页表再建立一张页表,称为页目录表。

基本分段存储管理方式

分段方式主要目的是更好地满足用户需要,一个段通常包含着一组属于一个逻辑模块的信息,分段对用户是可见的,用户编程时需要显式的写出段名。

一些名词的理解

(1)分段:段号S+段内偏移量W

段式管理方式按照用户进程中的自然段话分逻辑结构的,其逻辑地址由段号S与段内偏移量W两部分组成。段号的长度代表着一个作业最多有多少个段;段内偏移量决定最大段的长度。与页式系统不同的是,在夜市地址中,逻辑地址的页号和页内偏移量对用户是透明的,但在段式系统中,段号和段内偏移量必须由用户显式提供。

在这里插入图片描述

(2)段表:段号+段长+本段在主存中的起始地址

每个进程都有一张逻辑空间和内存空间映射的段表,其中,每个段表对应进程的一段,段表项记录该段在内存中的始址和长度。

在这里插入图片描述

在这里插入图片描述

(3)地址变换机构

  1. 从逻辑地址A中取出前几位为段号S,后几位为段内偏移量W。【注意】在段式存储管理系统中,逻辑地址一般以二进制数给出,而在页式存储管理中,逻辑地址一般以十进制数给出。在遇到这类情况时要分清是段式还是页式。
  2. 比较段号S和段表长度M,若S>=M,则产生越界中断,否则继续执行
  3. 段表中断号对应的段表项地址=段表始地址F+段号S*段表项长度。取出该段表项的前几位得到段长C,若段内偏移量>=C,则产生越界中断,否则继续执行。从这句话可以看出,段表项其实有【两个部分】,前几位是【段长】,后几位是【始址】
  4. 出去段表项中的始址b,计算EA=b+W,得到的真实地址EA访问内存
    在这里插入图片描述

(4)段的共享与保护

分段管理的保护方法主要有两种:一种是存取控制保护,另一种是地址越界保护。

地址越界保护将段表寄存器中的段表长度与逻辑地址中的段号比较,若段号大于段表长度,则产生越界中断;再将段表项中的段长和逻辑地址中的段内位移进行比较,若段内位移大于段长,也会产生越界中断。(页内偏移是不可能越界的)

分段、分页管理的对比

  1. 页是信息的物理单位,分页的主要目的是为了实现离散分配,提高利用率。分页仅仅是系统管理上的需要,完全是系统行为,对用户是不可见的;段是信息的逻辑单位,分段的主要目的是更好地满足用户需要,一个段通常包含着一组属于一个逻辑模块的信息,分段对用户是可见的,用户编程时需要显式的写出段名。

  2. 页的大小固定且由系统确定;段段长度不固定,由用户编写的程序决定

  3. 分页的用户进程地址空间是一维的,程序员只需要给出一个记忆符即可表示一个地址;分段的用户进程空间是二维的,程序员在标识一个地址时,既要给出段名,又要给出段内地址

  4. 分段比分页更容易实现信息的共享与保护。不能被修改的代码称为纯代码或可重入代码(不属于临界资源),这样的代码是可以共享的;可修改代码不可共享。

  5. 访问一个逻辑地址需要几次访存。

  6. 多页(单级页表):第一次访存查找内存中的页表;第二次访问目标单元;分段:第一次访问查找内存中的段表;第二次访存目标内存单元

  7. 与分页系统类似,分段系统中也可以引入快表机构,将近期访问过的段表项放到快表中,这样可以有一定几率少访问一次主存,加快地址变换速度。

段页式管理方式

在这里插入图片描述

在段页式管理系统中,作业多地址空间首先被分成若干逻辑段,每个段都有自己的段号,然后将每个段分成若干个大小固定的页。

在段页式管理系统中,作业的逻辑地址分为三部分:段号S+页号P+页内偏移量。为了实现地址变换,系统为每个进程建立一张段表,每个分段有一张页表。段表表项中至少有段号S,页表长度和页表始址;页表表项中至少包括页号和块号,此外,系统中还应有一个段表寄存器,指出作业的段表始址和段表长度。在一个进程中,段表只能有一个,而页表可以有很多个,但每个段表只有一张页表。

段页式管理方式中,每个进程只有1张段表,每个段表只有1张页表。

【段页式系统的地址变换机构】

在这里插入图片描述

3.2 虚拟内存管理

虚拟内存是基于"局部性原理"实现的,而局部性原理主要体现在两个方面:

【时间局部性】:程序中的某一条指令一旦执行,不久后该指令可能会再次执行;某数据被访问过,不久后可能再次被访问。产生时间局部性的原因是程序中存在着【大量循环】操作。【时间局部性】通过近来使用的数据和指令保存到【高速缓存存储器】中,并使用【高速缓存的层次结构】实现。

【空间局部性】:一旦程序访问了某个存储单元,在不久后,其附近的存储单元也将被访问,即程序在一段时间内所访问的地址,可能集中在一定范围内,因为指令通常是顺序存放、顺序执行的,数据也一般是以向量、数组、表等形式簇聚存储的。【空间局部性】通常使用较大的高速缓存,并将预取机制集成到高速缓存控制逻辑中实现。虚拟内存技术实际上建立了"内存-外存"的两级存储器结构,利用局部性原理实现高速缓存。

虚拟存储器的定义和特征

基于局部性原理,在程序装入时,将程序的一部分装入内存,而将其余部分留在外存,就可启动程序执行。在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需要的部分调入主存,然后继续执行程序。另一方面,操作系统将内存中暂时不使用的内容换出到外存上,从而腾出空间存放将要掉入内存的信息。这样,系统好像为用户提供了一个比实际内存大得多的存储器,称为虚拟存储器。

很显然的,虚拟存储器实际上并不存在(现实中存在的仅仅只是4G或8G的主存储),但是由于系统提供了部分装入、请求调入和置换功能后,给用户好像有这么个存储器的感觉。

虚拟存储器具有三个特点:

  • 多次性:也就是说,一个程序在运行时不用一次性全部装入内存,而是允许被分成多次调入主存内存运行。
  • 对换性:作业在运行时无须一直常驻内存,而允许在作业的运行过程中,进行换进和换出。
  • 虚拟性:指在逻辑上扩充容量

虚拟存储器容量大小不受内存和外存限制,和CPU寻址位数有关

虚拟内存技术的实现

虚拟内存的实现需要建立在离散分配的内存管理的基础上。虚拟内存的实现有以下三种方式:

  • 请求分页存储管理
  • 请求分段存储管理
  • 请求段页式存储管理

不管哪一种管理方式,都需要硬件支持。一般需要支持的有以下几个方面:

  • 一定容量的内存和外存
  • 页表机制(或段表机制),作为主要的数据结构
  • 中断机构,当用户程序要访问的部分尚未调入内存时,则发生中断
  • 地址变换机构,逻辑地址到物理地址的变换

请求分页管理方式

【请求分页系统】建立在【基本分页系统】基础之上,为了支持虚拟存储器的功能而增加了【请求调页功能】和【页面置换功能】。请求分页功能是当前最常用的一种实现虚拟存储器的方法。为了实现【请求分页 】,除了需要 一定量的内存和外存的计算机系统,还需要有:页表机制、缺页中断机构和地址变换机构。

页表机制

由于使用局部性原理,页面分多次调入主存,因此在作业运行过程中,必然会出现要访问的页面啊不在内存的情况,如何发现和处理这种请求是【请求分页系统】必须要解决的,因此在【请求页表项】中增加了4个字段。

【基本分页系统】的页表项:页号+物理内存中的块号

【请求分页系统】的页表项:页号+物理内存中的块号+状态位P+访问字段A+修改位M+外存地址

在这里插入图片描述

状态位P。用于指示该页是否已调入内存,供程序访问时参考 。

访问字段A。用于记录本页在一段时间内被访问的次数,或记录本页最近已有多长时间未被访问。供置换算法参考。

修改位M。表示该页在调入内存后是否被修改。供置换算法中【CLOCK置换算法】参考。

外存地址。用于指出该页在外存上的地址,通常是物理块号,供调入该页时参考。

缺页中断机构

在请求分页系统中,每当要访问的页面不在内存中时,便会产生一个【缺页中断】,请求操作系统将所缺的页调入内存。【注意】此时应将缺页的进程阻塞(调页完成后唤醒)。若内存中有空闲块,则分配一个块给将要调入内存的那个块,并修改页表中的相应【页表项】;若此时内存中没有空闲块,则要淘汰某页。

缺页中断与一般中断比较类似,但也有以下两个明显的区别:

  1. 在指令执行期间而非一条指令执行完后产生和处理中断信号,属于内部中断
  2. 一条指令在执行期间,可能产生多次缺页中断

地址变换机构

【请求分页系统】中的【地址变换机构】是在【分页系统】的【地址变换机构】的基础上,为实现虚拟内存,又增加了某些功能而形成的。

在这里插入图片描述

在进行地址变换时,现检索快表TLB:

  • 若找到要访问的表,则修改页表项中的【访问字段A】,如果是写指令还需要修改【修改位M】,然后利用页表项中给出物理块号和页内地址形成物理地址。
  • 若未找到该页的页表项,则应到内存中去查找页表,再对比页表项中的【状态页P】,看该页是否已调入内存;未调入内存则产生缺页中断,请求从外存把该页调入内存。

页面置换算法

OPT,最佳置换算法

OPT(Optimal),最佳置换算法选择的被淘汰的页面是以后永不使用的页面,或是在最长时间内不再被访问的页面,以便保证获得最低的缺页率。但我们没办法知道哪些页面是在未来最长时间不被访问的,所以【该算法无法实现】。

FIFO,先进先出算法

FIFO(First In First Out),先进先出算法有限淘汰最早进入的页面,即在内存中主流时间最久的页面。

FIFO算法会产生【所分配的物理块数增大而页故障数不减反增】的异常现象,被称为Belady异常。

LRU,最近最久未使用算法

LRU(Least Recently Used),最近最久未使用算法选择最近最长时间未访问过的页面予以淘汰。它认为过去一段时间内未访问过的页面,在最近的将来可能也不会被访问。

LRU算法的性能较好,但需要寄存器和栈的硬件支持。LRU算法是堆栈类算法。

CLOCK置换算法

CLOCK算法给每帧添加一个【使用位】。初始装入内存时,该页的使用位是1。当需要替换时,被扫到的页的帧1归0,当扫描时发现帧为0,则被淘汰。若全满,转一圈把所有帧都置0之后,再找第一个帧为0的页面被淘汰。

改进型CLOCK置换算法

设置两个位(使用位,修改位)。

淘汰顺序:(0,0)—(0,1)—(1,0)—(1,1)

以上淘汰顺序分表代表四种情况:

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

算法执行 如下操作步骤:

  1. 从指针的当前位置开始,扫描帧缓冲区。在这次扫描过程中,对使用位不做任何修改。选择到的第一个帧(0,0)用于替换。
  2. 若第1步失败,则重新扫描,查找(0,1)的帧。选择遇到第一个这样的帧用于替换。扫描过程中,对每个跳过的帧,他的实用为设置为0
  3. 若第2步失败,则指针将回到它的最初位置,且集合中所有帧的使用位均为0。重复第1步,并且有必要,重复第2步,以便可以找到 供替换的帧。

页面分配策略

驻留集是指给一个进程分配的物理页框的集合就是这个进程的驻留集。在设计留驻集需要考虑以下几点

驻留集大小

  1. 分配给一个进程的存储量越小,任何时候留驻在主存中的进程数就越多,从而可以提高处理机的时间利用效率
  2. 若一个进程在主存中的页数过少,则尽管有局部性原理,页错误率仍然会相对较高。
  3. 若页数过多,则由于局部性原理,给特定的进程分配更多的主存空间对该进程的错误率没有明显的影响。

基于这些因素,现代操作系统通常采用三种策略

  1. 【固定分配局部置换】。它为每个进程分配一定数目的物理块,整个运行期间都不改变(也就是,驻留集大小不变),称为固定分配。局部置换是指:若运行时缺页,则只能从该进程在内存中的页面中选出一页换出,然后调入需要的页面(也就是说,缺页时只能选进程自己的物理块进行置换)。
  2. 【可变分配全局置换】。它为整个系统中的每个进程分配一定数目的物理块,操作系统自身也保持一个空闲物理块队列(也就是驻留集大小可变),称为可变分配。当出现缺页时,可以从空闲物理块中选择一块分配给它(也就是说,可以将操作修通保留的空闲物理块分配给缺页进程,也可以将别的进程持有的物理块换到外存,再分配给缺页进程)
  3. 【可变分配局部置换】。为每个进程分配一定数目的物理块,当某个进程发生缺页时,只允许从该进程在内存的页面中选出一页换出,因此不会影响其他进程的运行。若进程在运行中频繁的缺页,则系统再为该进程分配若干物理块,直至该进程缺页率趋于适当程度;反之当进程运行中缺页率特别低时,则可由操作系统减少分配物理块给该进程(也就是说,驻留集大小可变,同时有机制可以使用不属于本进程的物理块)。

调入页面的时机

  • 【预调页策略】。根据局部性原理,一次调入若干相邻的页可能会比一次调入一页更高效。但目前预调页的成功率只有50%。故这种策略主要用于进程的【首次调入】,由程序员指出应先调入那些页。
  • 【请求调页策略】。进程在运行过程中因为访问的页面不在内存中而提出请求,由系统将所需页面调入内存。

总结来说,【预调页策略】是运行前的调入,【请求调页策略】就是运行时的调入,

从何处调入页面

请求分页系统中的外存主要有两部分:用于存放文件的【文件区】和用于存放对换页面的【对换区】。

【文件区】通常采用离散分配方式;【对换区】通常采用连续分配方式,故对换区的I/O速度比文件区的更快。

从何处调入页面就有三种情况

  • 【系统拥有足够的对换区空间】。可以全部从【对换区】调入所需页面。
  • 【系统缺少足够的对换区空间】。凡【不会被修改的文件】都从【对换区】调入;而当换出这些页面时,由于它们未被修改而不必再将它们换出。但对于那些【可能被修改的部分】,在将它们换出时须调到【对换区】,以后需要时再从对换区换入。
  • 【UNIX方式】。【与进程相关的文件】都放在【文件区】,故【未运行过的页面】都应从【文件区】调入。曾经运行过但又被换出的页面,由于放在【对换区】,因此下次调入时应从【对换区】调入。进程请求的共享页面若被其他进程调入内存,则【无须再从对换区】调入。

抖动

【抖动】是指:刚刚换出的页面马上又要换入内存,刚刚换入内存的页面马上又要换出内存,发生频繁的页面调度。

【抖动】产生的【原因】是某个进程频繁访问的页面数目高于可用的物理页帧数目。

解决方法:撤销部分进程

工作集

【工作集】是指在某段时间间隔内,进程要访问的页面集合。存放的是最近被访问的n个页面。

根据工作集的大小,确定留驻集的大小。一般来说,留驻集的大小要大于工作集的大小,否则在运行中会频繁缺页。

如,工作窗口为:{2,3,5,3,2},进程的工作集是:{2,3,5}。工作窗口为:{4,2,1,1,5},进程的工作集是:{1,2,4,5}。

区的更快。

从何处调入页面就有三种情况

  • 【系统拥有足够的对换区空间】。可以全部从【对换区】调入所需页面。
  • 【系统缺少足够的对换区空间】。凡【不会被修改的文件】都从【对换区】调入;而当换出这些页面时,由于它们未被修改而不必再将它们换出。但对于那些【可能被修改的部分】,在将它们换出时须调到【对换区】,以后需要时再从对换区换入。
  • 【UNIX方式】。【与进程相关的文件】都放在【文件区】,故【未运行过的页面】都应从【文件区】调入。曾经运行过但又被换出的页面,由于放在【对换区】,因此下次调入时应从【对换区】调入。进程请求的共享页面若被其他进程调入内存,则【无须再从对换区】调入。

地址翻译(考试重点)

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_之桐_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值