• 操作系统——内存管理



    前言

    本文的主要内容是操作系统中内存管理的基础知识,包括内存的基础知识、内存管理的简单介绍、内存空间的分配与回收以及内存空间的扩充,内存空间的分配与回收中主要掌握四种动态分区分配算法以及分页、分段和段页式管理方式,内存空间的扩充主要掌握覆盖技术和交换技术。


    一、内存的基础知识

    内存是用于存放数据的硬件,程序执行前需要先放到内存中才能被 CPU 处理。
    在多道程序环境下,系统中会有多个程序并发执行,也就是说会有多个程序的数据需要同时放到内存中,为了区分各个程序数据的存放位置,就需要给内存的存储单元编地址。
    内存地址从0开始,每个地址对应一个存储单元。存储单元如果按字节编址,则每个内存单元的大小为1字节,也就是8个二进制位;如果字长为16位的计算机按字编址,则每个内存单元的大小为1个字,也就是16个二进制位。
    地址长度的确定方法就是需要多少个二进制位才能表示相应数目的存储单元。例如4GB需要的地址长度是32位。
    进程通过指令的运行原理如下图所示。
    在这里插入图片描述
    比如要执行一个 x=x+1 的操作,会产生三条指令,每条指令对应着一个操作码,也就是需要 CPU 完成的操作,CPU 依次读取程序段中的指令然后执行。
    在上面的例子中,指令中直接给出了变量 x 的实际存放地址,也就是其物理地址,但实际在生成机器指令的时候并不知道该进程的数据会被放到什么位置,所以编译生成的指令中一般使用的是逻辑地址,也就是相对地址。
    相对地址也称为逻辑地址,绝对地址又称物理地址。
    从写程序到程序运行的过程如下图示所示。
    在这里插入图片描述
    编译是由编译程序将用户源代码编译成若干个目标模块,也是一个把高级语言编译为机器语言的过程;链接是由链接程序将编译后形成的一组目标模块以及所需库函数链接在一起,形成一个完整的装入模块;装入由装入程序将装入模块装入内存运行。
    链接的三种方式:静态链接、装入时动态链接和运行时动态链接。
    静态链接:在程序运行前,先将各目标模块及它们所需的库函数连接成一个完整的可执行文件(装入模块),之后不再拆开。
    装入时动态链接:将各目标模块装入内存时,边装入边链接。
    运行时动态链接:在程序执行中需要该目标模块时才对它进行链接,其优点是便于修改和更新,便于实现对目标模块的共享。
    装入的三种方式(即用三种不同的方法完成逻辑地址到物理地址的转换):绝对装入、静态重定位和动态重定位。
    绝对装入:在编译时,如果知道程序将放到内存中的哪个位置,编译程序将产生绝对地址的目标代码,装入程序按照装入模块中的地址,将程序和数据装入内存。绝对装入只适用于单道程序环境
    静态重定位:也称可重定位装入,编译、链接后的装入模块的地址都是从0开始的,指令中使用的地址、数据存放的地址都是相对于起始地址而言的逻辑地址,可以根据内存的当前情况,将装入模块装入到内存的适当位置,装入时对地址进行重定位,将逻辑地址变换为物理地址。静态重定位的特点是在一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能装入该作业,作业一旦进入内存后,在运行期间就不能再移动,也不能再申请内存空间。静态重定位方法用于早期的多道批处理操作系统。
    动态重定位:也称动态运行时装入,编译、链接后的装入模块的地址都是从0开始的,装入程序把装入模块装入内存后,并不会立即把逻辑地址转换为物理地址,而是把地址转换推迟到程序真正要执行时才进行,因此装入内存后所有的地址依然是逻辑地址,不过这种方式需要一个重定位寄存器(存放装入模块存放的起始位置)的支持。动态重定位方法用于现代操作系统。
    采用动态重定位时允许程序在内存中发生移动,并且可将程序分配到不连续的存储区中,在程序运行前只需装入它的部分代码即可投入运行,然后在程序运行期间根据需要动态申请分配内存,便于程序段的共享,可以向用户提供一个比存储空间大得多的地址空间。
    对内存的基础知识简单的总结一下,如下图所示。
    在这里插入图片描述


    二、内存管理简介

    内存管理的内容包括内存空间的分配与回收、内存空间的扩充、地址转换以及内存保护。
    ①内存空间的分配与回收
    操作系统负责内存空间的分配与回收。操作系统需要记录内存中哪些区域已经被分配出去了,哪些区域是空闲的;内存中有很多位置可以存放进程时,该进程该放在哪里;当进程运行结束之后,如何将进程占用的内存空间回收等。
    ②内存空间的扩充
    操作系统需要提供某种技术从逻辑上对内存空间进行扩充。比如要运行的游戏所占的内存超过电脑的内存很多时,游戏为何还是能够顺利的运行,这就涉及到了操作系统的虚拟性。
    ③地址转换
    操作系统需要提供地址转换功能,负责程序的逻辑地址与物理地址的转换。
    用到的装入方法有:绝对装入、静态重定位和动态重定位。
    ④内存保护
    操作系统需要提供内存保护功能,保证各进程在各自存储空间内运行,互不干扰。
    如下图所示,各进程只能访问自己对应的内存空间,而对于操作系统和其他进程的内存空间是不允许访问的。
    在这里插入图片描述
    内存保护的方法有:设置上下限寄存器和利用重定位寄存器、界地址寄存器进行越界检查。
    设置上下限寄存器:在 CPU 中设置一对上、下限寄存器,存放进程的上、下限地址,进程的指令要访问某个地址时,CPU 要检查是否越界,只有不越界时,才允许当前进程进行访问,否则禁止访问。
    利用重定位寄存器、界地址寄存器进行越界检查:重定位寄存器中存放的是进程的起始物理地址,界地址寄存器中存放的是进程的最大逻辑地址。
    对内存管理简介这部分内容总结一下,如下图所示。
    在这里插入图片描述


    三、内存空间的分配与回收

    1、连续分配管理方式

    连续分配指的是为用户进程分配的必须是一个连续的内存空间。
    连续分配管理方式包括单一连续分配、固定分区分配和动态分区分配。

    ⑴单一连续分配

    单一连续分配方式中,内存被分为系统区和用户区,如下图所示。
    在这里插入图片描述
    系统区通常位于内存的低地址部分,用于存放操作系统相关数据,用户区用于存放用户进程相关数据。内存中只能有一道用户程序,用户程序独占整个用户区空间。
    该方法的优点是:实现简单;无外部碎片;可以采用覆盖技术扩充内存;不一定需要采取内存保护。
    该方法的缺点是:只能用于单用户、单任务的操作系统中;有内部碎片;存储器利用率极低。
    内部碎片:分配给某进程的内存区域中,如果有些部分没有用上,就是内部碎片。
    外部碎片:指内存中的某些空间分区由于太小而难以利用。

    ⑵固定分区分配

    20世纪60年代出现了支持多道程序的系统,为了能在内存中装入多道程序,且这些程序之间又不会相互干扰,于是将整个用户空间划分为若干个固定大小的分区,在每个分区中只装入一道作业,这样就形成了最早的、最简单的一种可运行多道程序的内存管理方式。
    固定分区分配又包括分区大小相等和分区大小不相等两种,如下图所示。
    在这里插入图片描述
    分区大小相等的情况缺乏灵活性,但是很适合用于用一台计算机控制多个相同对象的场合。分区大小不相等增加了灵活性,可以满足不同大小的进程需求,根据常在系统中运行的作业大小情况进行划分。一般多划分小分区,适量的中等分区和少量的大分区。
    操作系统需要建立一个数据结构——分区说明表来实现各个分区的分配与回收,每个表项对应一个分区,通常按分区大小排列,每个表项包括对应分区的大小、起始地址和状态(是否已分配)。
    当某用户程序要装入内存时,由操作系统内核程序根据用户程序大小检索该表,从中找到一个能满足大小的、未分配的分区,将它分配给该程序,然后修改状态为已分配。
    该方法的优点是:实现简单,无外部碎片。
    该方法的缺点是:当用户程序太大时,可能所有的分区都不能满足需求,此时不得不采用覆盖技术来解决,但这样会降低性能;此外,该方法会产生内部碎片,内存利用率低。

    ⑶动态分区分配

    动态分区分配又称为可变分区分配,这种分配方式不会预先划分内存分区,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的大小正好适合进程的需要,因此系统分区的大小和数目是可变的。
    ①系统要用什么样的数据结构记录内存的使用情况?
    系统会用空闲分区表空闲分区链两种方法记录内存的使用情况。空闲分区表中,每个空闲分区对应一个表项,表项中包含分区号、分区大小、分区起始地址以及状态等信息;空闲分区链中,每个分区的起始部分和末尾部分分别设置前向指针和后向指针,起始部分处还可记录分区大小等信息。
    空闲分区表和空闲分区链的简单表示如下图所示。
    在这里插入图片描述
    ②当很多个空闲分区都能满足需求时,应当选择哪个分区进行分配?
    把一个新作业装入内存时,须按照一定的动态分区分配算法从空闲分区表或空闲分区链中选出一个分区分配给该作业。动态分区分配算法会在后面介绍到,这里不再展开。
    ③如何进行分区的分配与回收操作?
    在进行分区分配时,按照动态分区分配算法选择了某一分区后,在其对应的空闲分区表或空闲分区链中进行数据的更新即可。
    在进行分区回收时,分以下几种情况:
    情况一:回收区的后面有一个相邻的空间分区。
    这种情况下将两个相邻的空间分区合并为一个,并更新分区大小和起始地址。
    情况二:回收区的前面有一个相邻的空间分区。
    这种情况下仍然将两个相邻的空间分区合并为一个,并更新分区大小和起始地址。
    情况三:回收区的前、后各有一个相邻的空间分区。
    这种情况下要将三个相邻的空间分区合并为一个,并更新分区大小和起始地址。
    情况四:回收区的前、后都没有相邻的空间分区。
    这种情况下需要新增一个表项,并把分区号、分区大小、起始地址和状态填进去。
    总的来说,相邻的空间分区要合并。
    动态分区分配没有内部碎片,但有外部碎片。
    如果内存中空闲空间的总和本来可以满足某进程的要求,但由于进程需要的是一整块连续的内存空间,所以这些碎片不能满足进程的需求,但是可以通过紧凑(或拼凑)技术来解决外部碎片。
    对连续分配管理方式这部分内容总结一下,如下图所示。
    在这里插入图片描述

    2、动态分区分配算法

    动态分区分配算法需要解决的问题是:当很多个空闲分区都能满足需求时,应该选择哪个分区进行分配。
    动态分区分配算法有首次适应算法(First Fit)、最佳适应算法(Best Fit)、最坏适应算法(Worst Fit)和邻近适应算法(Next Fit)。

    ⑴首次适应算法(First Fit)

    算法思想:每次都从低地址开始查找,找到第一个能满足大小的空闲分区。
    实现:空闲分区按地址递增的次序排列,每次分配内存时顺序查找空闲分区表或空闲分区链,找到大小能满足要求的第一个空闲分区分配给进程,然后对空闲分区表或空闲分区链的内容进行更新,这种方法不需要对链表重新排序。

    ⑵最佳适应算法(Best Fit)

    算法思想:由于动态分区分配是一种连续分配方式,其为各进程分配的空间必须是连续的一整片区域。因此为了保证当大进程到来的时候能有连续的大片空间,可以尽可能多地留下大片的空闲区,优先使用更小的空闲区。
    实现:空闲分区按容量递增的次序排列,每次分配内存时顺序查找空闲分区表或空闲分区链,找到大小能满足要求的第一个空闲分区分配给进程(这时找到的第一个空间分区是既满足申请又是容量最小的),然后对空闲分区表或空闲分区链的内容进行更新并重新排序。
    最佳适应算法的缺点:由于该算法每次都是选最小的分区进行分配,因此会留下越来越多的、很小的、难以利用的内存块,所以这种方法会产生很多的外部碎片。

    ⑶最坏适应算法(Worst Fit)

    最坏适应算法又称最大适应算法(Largest Fit)。
    算法思想:为了解决最佳适应算法的问题,即留下太多难以利用的小碎片,可以在每次分配时优先使用最大的连续空间区,这样分配后剩余的空闲区就不会太小,更方便使用。
    实现:空闲分区按容量递减的次序排列,每次分配内存时顺序查找空闲分区表或空闲分区链,找到大小能满足要求的第一个空闲分区分配给进程,然后对空闲分区表或空闲分区链的内容进行更新并重新排序。
    最坏适应算法的缺点:由于该算法每次都是选最大的分区进行分配,虽然可以让分配后留下的空闲区更大、更可用,但是这种方式会导致较大的连续空间区被迅速用完,如果之后有大进程到达,就没有内存分区可用了。

    ⑷邻近适应算法(Next Fit)

    算法思想:首次适应算法每次都是从链头开始查找的,这可能会导致低地址部分出现很多小的空闲分区,而每次分配查找时,都要经过这些分区,因此也增加了查找的开销,如果每次都从上次查找结束的位置开始检索,就能解决查找开销较大的问题。
    实现:空闲分区按地址递增的次序排列,可以排成一个循环链表,每次分配内存时从上次查找结束的位置开始查找空闲分区表或空闲分区链,找到大小能满足要求的第一个空闲分区分配给进程,这种方法不需要对链表重新排序。
    首次适应算法每次都要从头查找,每次都需要检索低地址的小分区,但是这种规则也决定了当低地址部分有更小的分区可以满足需求时,会更有可能用到低地址部分的小分区,也会把高地址部分的大分区保留下来。
    邻近适应算法的缺点:邻近适应算法的规则可能会导致无论低地址还是高地址部分的空闲分区都有相同的概率被使用,也就导致了高地址部分的大分区更可能被使用从而划分为小分区,最后导致无大分区可用。
    综合来看,四种算法中,首次适应算法的效果更好。
    对动态分区分配算法这部分介绍到的四种算法简单的总结一下,如下表所示。
    在这里插入图片描述

    3、基本分页存储管理的概念

    前面介绍到的两种连续分配方式:固定分区分配和动态分区分配,它们都有一定的缺点。
    固定分区分配缺乏灵活性,会产生大量的内部碎片,内存利用率很低。动态分区分配会产生很多的外部碎片,虽然可以用紧凑技术来处理,但是时间代价很高。
    如果允许将一个进程分散地装入到许多不相邻的分区中,便可以充分地利用内存,而无需再进行紧凑。基于这种思想,就产生了非连续分配方式,或者离散分配方式。
    连续分配为用户进程分配的必须是一个连续的内存空间,而非连续分配为用户进程分配的可以是一些分散地内存空间。
    基本分页存储管理的思想:把内存分为一个个相等的小分区,再按照分区大小把进程拆分成一个个小部分
    在这里插入图片描述
    如上图所示,把内存空间分为一个个大小相等的分区,每个分区就是一个页框,或称页帧内存块物理块。每个页框有一个编号,也就是页框号(或者页帧号、内存块号、物理块号),页框号是从0开始的。
    将用户进程的地址空间也分为与页框大小相等的一个个区域,称为页或页面,每个页面也有一个编号,即页号,页号也是从0开始的。
    需要注意的是,进程的最后一个页面可能没有一个页框那么大,这样的话就会产生内部碎片,所以页框设置的不能太大,否则可能产生过大的内部碎片。
    操作系统以页框为单位为各个进程分配内存空间,进程的每个页面分别放入一个页框中,进程的页面与内存的页框有一一对应的关系。各个页面不必连续存放,也不必按先后顺序来,可以放到不相邻的各个页框中。
    采用分页存储方法最重要的就是解决逻辑地址到物理地址的转化。
    下图是一个具体的例子。
    在这里插入图片描述
    比如 CPU 要访问逻辑地址为80的内存单元,如何计算其物理地址。首先可以确定,逻辑地址为80的内存单元在1号页,该页在内存中的起始位置是450,逻辑地址为80相对于该页的起始地址而言,偏移量是30。所以逻辑地址为80的内存单元对应的实际物理地址是:450+30=480。
    逻辑地址到物理地址的计算步骤:算出逻辑地址对应的页号——>要知道该页号对应的页面在内存中的起始地址——>算出逻辑地址在页面内的偏移量——>物理地址 = 页面地址 + 页内偏移量。
    页号 = 逻辑地址/页面长度 (取整数)
    页内偏移量 = 逻辑地址%页面长度 (取余数)
    页面在内存中的起始位置:操作系统需要用某种数据结构记录进程各个页面的起始位置。

    实际中一般都是采用二进制来表示的,下图中红色的表示的就是页号,黑色的表示页内偏移量。
    在这里插入图片描述
    如果每个页面大小为 2 k 2^k 2kB,用二进制数表示逻辑地址,则末尾 k 位为页内偏移量,其余部分就是页号。所以如果让每个页面的大小为2的整数幂,计算机就可以很方便的得出一个逻辑地址对应的页号和页内偏移量。
    为了能知道进程的每个页面在内存中存放的位置,操作系统要为每个进程建立一张页表,具体的内容如下图所示。
    在这里插入图片描述
    对基本分页存储管理这部分内容简单的总结一下,如下图所示。
    在这里插入图片描述

    4、地址变换机构

    ⑴基本地址变换机构

    基本地址变换机构适用于实现逻辑地址到物理地址转换的一组硬件机构,它可以借助进程的页表将逻辑地址转换为物理地址。
    通常会在系统中设置一个页表寄存器,存放页表在内存中的起始地址 F 和页表长度 M。进程未执行时,页表的始址和页表长度放在进程控制块中,当进程被调度时,操作系统内核会把它们放到页表寄存器中。
    逻辑地址到物理地址的转换流程如下图所示。
    在这里插入图片描述
    逻辑地址到物理地址的变换过程如下图所示。
    在这里插入图片描述
    下图是一个逻辑地址到物理地址转换的例子。
    在这里插入图片描述
    对基本地址变换机构这部分内容简单的总结一下,如下图所示。
    在这里插入图片描述

    ⑵具有快表的地址变换机构

    局部性原理有时间局部性和空间局部性。
    时间局部性:如果执行了程序中的某条指令,那么不久后这条指令很有可能再次执行,如果某个数据被访问过,不久之后该数据很可能再次被访问,因为程序中会存在大量的循环。
    空间局部性:一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也很有可能被访问,因为很多数据在内存中都是连续存放的。

    快表又称联想寄存器,是一种访问速度比内存快很多的高速缓冲存储器,用来存放当前访问的若干页表项,以加速地址变换的过程。与此对应的,内存中的页表常称为慢表。
    快表的应用如下图所示,在快表命中后就不需要再访问内存了,和之前相比提高了访问的效率。
    在这里插入图片描述
    引入快表后的地址变换过程为:①CPU给出逻辑地址,由某个硬件算得页号、页内偏移量,将页号与快表中的所有页号进行比较;②如果找到匹配的页号,说明要访问的页表项在快表中有副本,则直接从中取出该页对应的内存块号,再将内存块号与页内偏移量拼接形成物理地址,最后,访问该物理地址对应的内存单元。因此,若快表命中,则访问某个逻辑地址仅需一次访存即可;③如果没有找到匹配的页号,则需要访问内存中的页表,找到对应页表项,得到页面存放的内存块号,再将内存块号与页内偏移量拼接形成物理地址,最后,访问该物理地址对应的内存单元。因此,若快表未命中,则访问某个逻辑地址需要两次访存。需要注意的是,在找到页表项后,应同时将其存入快表,以便后面可能的再次访问,但若快表已满,则必须按照一定的算法对旧的页表项进行替换。
    由于查询快表的速度比查询页表的速度快很多,因此只要快表命中,就可以节省很多时间。
    下图是引入快表后应用的一个例子。
    在这里插入图片描述
    基本地址变换机构和具有快表的地址变换机构对比如下表所示。
    在这里插入图片描述

    5、两级页表

    单级页表存在的问题:
    问题一:页表必须连续存放,因此当页表很大时,需要占用很多个连续的页框;
    问题二:没必要让整个页表都常驻内存,因为进程在一段时间内可能只需要访问某几个特定的页面就可以正常运行。
    怎么解决问题一呢?可以将长页表进行分组,使每个内存块刚好可以放入一个分组,此外,要为离散分配的页表再建立一张页表,称为页目录表(或称为外层页表/顶层页表)。
    将长页表进行分组后如下图所示。
    在这里插入图片描述
    两级页表如下图所示。
    在这里插入图片描述
    地址变换如下图所示。
    请添加图片描述
    问题二的解决方法是:在需要访问页面时才把页面调入内存,这里要用到虚拟存储技术,可以在页表项中增加一个标志位,用于表示该页面是否已经调入内存。如果想要访问的页面不在内存中,则产生缺页中断,即内中断,然后将目标页面从外存调入内存。
    多级页表中需要注意的两个问题:
    ① 采用多级页表机制,则各级页表的大小不能超过一个页面。(比如页面大小为1KB,1KB = 2 10 2^{10} 210KB,所以各级页表的大小最多由10位二进制数表示)
    ② N 级页表访问一个逻辑地址的访存次数为 N+1 次。
    需要注意问题的举例如下图所示。
    在这里插入图片描述
    对两级页表这部分内容简单的总结一下,如下图所示。
    在这里插入图片描述

    6、基本分段存储管理方式

    分段存储管理与分页存储管理方式最大的不同就是离散分配时所分配地址空间的基本单位不同。
    分段方式中进程的地址空间是按照程序自身的逻辑关系划分为若干个段,每个段都有一个段名,且每段从0开始编址。
    内存分配规则:以段为单位进行分配,每个段在内存中占据连续空间,但各段之间可以不相邻。
    分段存储管理方式中的内存分配规则示意图如下图所示。
    在这里插入图片描述
    由于是按照逻辑功能模块划分, 用户编程更方便,程序的可读性高。
    编译程序会将段名转换为段号。
    分段系统中的逻辑地址由段号(段名)和段内地址(段内偏移量)组成,段号的位数决定了每个进程最多可以分几个段,段内地址位数决定了每个段的最大长度是多少。
    程序分为多个段,各段离散地装入内存,为了保证程序能正常运行,就必须从物理内存中找到各个逻辑段的存放位置,所以就需要为每个进程建立一张段映射表,也就是段表。如下图所示。
    在这里插入图片描述
    各个段表项的长度是相同的。段号可以是隐含的,不占存储空间。
    下图是分段存储管理方式的具体流程,与分页方式主要的不同是第四步,由于分段存储管理方式中的段长是不相同的,因此要进行比较看有没有越界的产生,而分页存储管理方式中的页面长度是相同的,因此不用比较。
    请添加图片描述
    分页与分段管理方式的对比:
    页是信息的物理单位,分页的主要目的是为了实现离散分配,提高内存利用率,分页仅仅是系统管理上的需要,完全是系统行为,对用户是不可见的;段是信息的逻辑单位,分段的主要目的是更好地满足用户需求,一个段通常包含着一组属于一个逻辑模块的信息。分段对用户是可见的,用户编程时需要显式的给出段名。
    页的大小固定且由系统决定,段的长度不固定,它取决于用户编写的程序。
    分页的用户进程地址空间是一维的,程序员只需给出一个记忆符即可表示一个地址;分段的用户进程地址空间是二维的,程序员在标识一个地址时,既要给出段名,也要给出段内地址。
    分段比分页更容易实现信息的共享和保护。
    要实现共享,只需要让各进程的段表项指向同一个段即可,能共享的只是不能被修改的代码,也就是纯代码或可重入代码,这不属于临界资源,而可修改的代码是不能共享的,比如代码段中包含很多的变量。
    分页难以共享的原因是页面不是按照逻辑模块划分的,如下图所示。
    在这里插入图片描述
    对基本分段存储管理方式这部分内容简单的总结一下,如下图所示。
    在这里插入图片描述

    7、段页式管理方式

    分页管理的优点是内存空间利用率高,不会产生外部碎片,只会有少量的页内碎片,缺点是不方便按照逻辑模块实现信息的共享和保护;分段管理的优点是很方便按照逻辑模块实现信息的共享和保护,缺点是如果段长过大,为其分配很大的连续空间会很不方便,此外,该方式会产生外部碎片。
    段页式管理方式的示意图如下图所示。
    在这里插入图片描述
    段页式就是在分段的基础上将段内地址拆分为页号和页内偏移量,如下图所示。
    在这里插入图片描述
    一个进程会对应一个段表,但可能会对应多个页表。
    段页式管理方式的具体流程如下图所示。
    请添加图片描述
    对段页式管理方式这部分内容简单的总结一下,如下图所示。
    在这里插入图片描述


    四、内存空间的扩充

    1、覆盖技术

    覆盖技术用来解决程序大小超过物理内存总和的问题。
    覆盖技术的思想是:将程序分为多个段(多个模块),常用的段常驻内存,不常用的段只在需要时调入内存。
    内存中分为一个固定区和若干个覆盖区,需要常驻内存的段放在固定区中,调入后就不再调出,除非运行结束。不常用的段放在覆盖区,需要用到时调入内存,用不到时就调出内存。
    覆盖技术的一个应用例子如下图所示。
    在这里插入图片描述
    通过这个例子,我们可以按照自身逻辑结构,让那些不可能同时被访问的程序段共享同一个覆盖区,这样就能够减少内存的占用。
    这种方法必须由程序员声明覆盖结构,操作系统完成自动覆盖。其缺点是对用户不透明,从而增加了用户编程的负担。
    覆盖技术只用于早期的操作系统中,现在已成为历史,不再使用。

    2、交换技术

    交换技术也称对换技术,其设计思想是:内存空间紧张时,系统将内存中某些进程暂时换出外存,把外存中某些已具备运行条件的进程换入内存。采用交换技术时,进程在内存与磁盘间动态调度。
    交换技术用到了中级调度,也就是内存调度,该调度就是要决定将哪个处于挂起状态的进程重新调入内存。
    下图是一个交换技术的例子。
    在这里插入图片描述
    上图中,在某一时刻,如果内存空间紧张时,就将内存中的某些进程换出到外存,而进程相关的 PCB (记录进程被换入到外存中的位置)会保留在内存中并插入到挂起队列里,当内存空间不紧张时,再将其换入到内存执行。
    交换技术中有以下几个问题需要解答:
    ①应该在外存(磁盘)的什么位置保存被换出的进程?
    在具有对换功能的操作系统中,通常把磁盘空间分为文件区和对换区两部分。文件区主要用于存放文件,追求存储空间的利用率,因此对文件区空间的管理采用离散分配方式。对换区空间只占磁盘空间的小部分,被换出的进程数据就存放在对换区。由于对换区的速度直接影响到系统的整体速度,因此对换区空间的管理主要追求换入换出的速度,因此通常对换区采用连续分配方式。对换区的 I/O 速度比文件区的更快。
    ②什么时候应该交换?
    交换通常在许多进程运行且内存吃紧时进行,而系统负荷降低就暂停。比如:在发现许多进程运行时经常发生缺页,就说明内存紧张,此时可以换出一些进程,如果缺页率明显下降,就可以暂停换出。
    ③应该换出哪些进程?
    可优先换出阻塞进程;可换出优先级低的进程;为了防止优先级低的进程在被调入内存后很快又被换出,有的系统还会考虑进程在内存的驻留时间。需要注意的是 PCB 会常驻内存,不会被换出到外存。
    覆盖技术与交换技术的区别是:覆盖是在同一个程序或进程中进行的,而交换是在不同进程或作业之间发生的。
    对内存空间的扩充这部分内容简单的总结一下,如下图所示。
    在这里插入图片描述


    总结

    以上就是操作系统——内存管理的所有内容了,内存管理是操作系统中比较重要的知识点,应当对本文中提到的四种动态分区分配算法、分页管理方式、分段管理方式、段页式管理方式、覆盖技术和交换技术等内容加以掌握。
    参考视频:
    内存的基础知识
    内存管理的概念
    覆盖与交换
    连续分配管理方式
    动态分区分配算法
    基本分页存储管理的概念
    基本地址变换机构
    具有快表的地址变换机构
    两级页表
    基本分段存储管理方式
    段页式管理方式

  • 相关阅读:
    逆傅里叶变IFFT原始信号恢复方法研究-附Matlab代码
    【MySQL进阶】深入理解InnoDB数据页结构
    IPV4的未来替代品!一文读懂IPV6的优势特点和地址类型
    Vue.js核心技术解析与uni-app跨平台实战开发学习笔记 第6章 Vue.js路由 6.3 路由重定向以及动画路由 && 6.4 路由传参
    RDB是什么?·
    pandas写入MySQL
    工作中使用Redis的10种场景
    imx6ul链接地址、运行地址、加载地址、位置无关、mmu的关系
    编程学习的方向与赛道的选择没有最优解的
    大型前端应用如何做系统融合?
  • 原文地址:https://blog.csdn.net/weixin_42570192/article/details/126101323