【操作系统】3.1内存管理(内存基础、内存管理)

内存的基础知识

1. 什么是内存、有什么作用

  • ⭐内存是用于存放数据的硬件。程序执行前需要先放到内存中才能被CPU处理,如果高速CPU直接和慢速的外存进行数据的交互,有速度矛盾

思考:
在多道程序环境下,系统中会有多个程序并发执行,也就是说会有多个程序数据需要同时放入内存中,那么,如何区分各个程序的数据是放在什么地方呢?
方案:
给内存的存储单元编地址

  1. 内存地址从0开始,每个地址对应一个存储单元
  2. 内存中也有一个一个的“小房间”,每个小房间就是以一个存储单元
  3. 如果计算机“按字节编址”,则每个存储单元大小为1字节,即1B,即8个二进制位
  4. 如果字长16位的计算机“按字编址”,则每个存储单元大小为1个字,每个字的大小为16个二进制位

补充知识:几个常用的数量单位
一台电脑内存有4GB:是指该内存中可以存放4*230个字节,如果是按字节编址的,就是有4 * 230= 232个存储单元,这么多存储单元需要232个地址才能一个一个表示,所以地址需要用32个二进制位来表示(0 ~ 232-1)
210 = 1K
220 = 1M
230 = 1G

2. 进程运行的基本原理

  1. 指令:

    1. 以执行为例x=x+1:首先系统会将代码编译成CPU可以识别的机器语言(指令):
      在这里插入图片描述
      CPU会依次执行程序段中的指令
      1. 指令的前面几位为操作码(红色),可以告诉CPU让它做什么(数据传达、加法…)
      2. 后面的为参数,如指令1,表示从01001111中取出数据,将数据传输到00000011的寄存器中
    2. 具体的执行过程:
      代码会“翻译”成CPU可以识别的指令,这些指令会告诉CPU该去内存的哪个地址存/取数据,这个数据应该做什么样的处理
      在这里插入图片描述
      首先CPU根据 指令1: 从01001111中取出数据,并将数据传输到00000011的寄存器中,接着执行 指令2: 将寄存器00000011中的数据 + 00000001(即+1),再执行 指令3: 将寄存器00000011中的计算结果,再传回到地址0101111中
  2. ⭐逻辑地址&相对地址:

    思考:
    上面的例子中直接给出了数据的实际存放地址(物理地址),但在实际中生产机器指令的时候并不知道该进程的数据会被放到什么位置,所以编译生成的指令一般使用的是逻辑地址(相对地址)

    • 指令中的地址:编译时产生的指令,只关心“相对地址”,实际放入内存中时再想办法通过起始地址找到“绝对地址”
    • 相对=逻辑,绝对=物理
  3. ⭐从写程序到程序运行:

    1. 编译:由编译程序将用户源代码文件(* .c文件)编译成若干个目标模块(* .o文件)(编译就是把高级语言翻译成机器语言)
    2. 链接:由连接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的装入模块
    3. 装入:由装入程序将装入模块装入内存运行
      在这里插入图片描述
  4. ⭐装入的三种方式:

    1. 绝对装入:——装入模块直接用绝对地址
      1. 在编译时,如果程序员知道程序将放到内存的哪个位置,编译程序将产生绝对地址的目标代码。装入程序按照装入模块中的地址,将程序和数据装入内存(编译、链接后得到的装入模块的指令直接就使用了绝对地址
      2. 缺点:绝对装入只适用于单道程序环境
        在这里插入图片描述
    2. 静态重定位:——装入模块用逻辑地址,装入时转换为绝对地址
      1. 编译、链接后的装入模块的地址都是从0开始的逻辑地址,指令中使用的地址、数据存放的地址都是相对于起始地址而言的逻辑地址。可根据内存的当前情况,将装入模块装入到内存的适当位置,装入时对地址进行“重定位”,将逻辑地址转换为物理地址(地址变换是在装入时一次性完成的
      2. 缺点:静态重定位时在一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能装入该作业。作业一旦进入内存后,在运行期间就不能再移动,也不能再申请内存空间
        在这里插入图片描述
    3. ⭐⭐动态重定位:————装入模块用逻辑地址,装入内存也使用逻辑地址,要用时才转换为绝对地址
      1. 编译、链接后的装入模块的地址都是从0开始的逻辑地址,装入程序把装入模块装入内存后,并不会立即把逻辑地址转换为物理地址,而是 把地址转换推迟到程序真正要执行时 才进行。因此 装入内存后所有的地址依然是逻辑地址 。这种方式需要一个重定位寄存器的支持
      2. 优点
        1. 允许程序在内存中发生移动
        2. 可以将程序分配到不连续的存储区中:再程序运行前只需要装入它的部分代码即可投入运行,然后再程序运行期间,根据需要动态申请分配内存
        3. 便于程序段的共享,可以向用户提供一个比存储空间大得多的地址空间

    在这里插入图片描述

  5. 链接的三种方式:

    1. 静态链接:在程序运行之前,将各个目标模块以及它们所需的库函数链接成一个完整的可执行文件(装入模块),之后便不再拆开
      在这里插入图片描述
    2. 装入时动态链接:将各个目标模块装入内存时,边装入边链接的链接方式
      在这里插入图片描述
    3. 运行时动态链接:在程序执行中需要该目标模块时,才对他进行链接。其优点是便于修改和更新,便于实现对目标模块的分享
      在这里插入图片描述

内存管理

  1. 1. 操作系统负责内存空间的分配与回收(下一节内容)

    1. 操作系统要如何记录哪些内存区域已经被分配出去了,哪些还空闲?
    2. 当一个进程要调入内存时,很多位置都可以放,那么要放到哪个位置?
    3. 当进程运行结束后,如何将进程占用的内存空间回收?
    1. 传统的存储管理方式:(一次性、驻留性
      1. 连续分配方式:
        1. 单一连续分配
        2. 固定分区分配
        3. 动态分区分配
      2. 非连续分配方式:
        1. 基本分页存储管理
        2. 基本分段存储管理
        3. 基本段页式存储管理
    2. 虚拟内存技术(见下)
  2. 2. 操作系统需要提供某种技术从逻辑上对内存空间扩充

    4GB内存运行60GB的游戏
    早期的计算机内存很小,因此会出现内存不够的情况。后来人们引入了覆盖技术,用来解决“程序超过物理内存总和”的问题

    1. 覆盖技术 :

      在同一个程序或进程中的
      1. 覆盖技术的思想:将程序分成多个段(多个模块)。常用的段常驻内存,不常用的段需要调入内存
      2. 内存中分为一个“固定区”和若干个“覆盖区”
      3. 需要常驻内存的段放在 “固定区” 中,调入后就不再调出(除非运行结束)
      4. “覆盖区” 中的程序段会在运行当中根据需要调入调出
      5. 必须由程序员声明覆盖结构,操作系统完成自动覆盖
      6. 缺点:对用户不透明,增加了编程困难,用于早期操作系统,已成为历史
    2. 交换技术:

      在不同的进程或作业之间
      1. 交换技术的思想:内存空间紧张时,系统将内存中的某些进程暂时换出外存,把外存中某些已经具备运行条件的进程换入内存(进程在内存与磁盘之间动态调度)
      2. 注意:PCB会常驻内存,不会被换出,保存进程的信息,保证管理换出的进程
      3. 思考:
        1. 应该在外存的什么位置保存被换出的进程?
          具有对换功能的操作系统中,通常把磁盘空间分为文件区和对换区两部分。文件区主要用于存放文件,主要追求存储空间的利用率,因此对文件区空间的管理采取离散分配的方式;对换区空间只占磁盘空间的一小部分,被换出的数据就存储在兑换区,兑换区通常采用I/O速度更快的连续分配方式
        2. 什么时候应该交换?
          交换通常在许多进程运行且内存吃紧时进行,而系统负荷降低就暂停。例如:在发现许多进程运行时经常发生缺页,就说明内存紧张,此时可以换出一些进程;如果缺页率明显下降,就可以暂停换出
        3. 应该换出哪些程序?
          可以优先换出阻塞态的进程,可以换出优先级比较低的进程,同时防止优先级低的进程发生饥饿,会考虑进程在内存的驻留时间
    3. ⭐虚拟存储技术

      1. 传统存储管理方式的特征和缺点:

        1. 一次性:作业必须一次性全部装入内存后才能开始运行。会造成两个问题:
          1. 作业很大时,不能全部装入内存,导致大作业无法运行
          2. 当大量作业要求运行时,由于内存无法容纳所有作业,因此只有少量作业能运行,导致多道程序并发度下降
        2. 驻留性:一旦作业被装入内存,就会一直驻留在内存中,直至作业运行结束。事实上,在一个时间段内,只需要访问作业的一小部分数据即可正常运行
      2. 局部性原理

        1. 时间局部性:如果执行了程序中的某条指令,那么不久后这条指令很有可能再次执行;如果某条数据被访问过,那么不久之后该数据很有可能再次被访问(因为程序中存在大量的循环)
        2. 空间局部性:一旦程序访问了某个存储单元,在不久之后其附近的存储单元也很有可能被访问(因为很多数据在内存中都是连续存放的)
        3. 高速缓冲技术:
          1. 思想:将近期会频繁访问到的数据放到更高速的存储器中,暂时用不着的数据放在更低速的存储器中
          2. 存取速度:寄存器>高速缓存>内存>外存
          3. 容量:外存>内存>高速缓存>寄存器
          4. 应用快表机构就是将近期常访问的页表项副本放在更高速的联想寄存器当中
      3. 虚拟内存的定义和特征

        1. 定义:
          1. 基于局部性原理,在程序装入时,可以将程序中很快会用到的部分装入内存,暂时用不到的部分留在外存,就可以让程序开始执行
          2. 在程序执行的过程中,当所访问的信息不再内存中时,由操作系统负责将所需信息从外存调入内存,然后继续执行程序
          3. 内存空间不够,由操作系统负责将内存中暂时不用的信息换出到外存
          4. 在操作系统的管理下,在用户看来似乎有一个比实际内存大得多的内存,这就是虚拟内存(逻辑上的扩充
        2. 易混知识点
          1. 虚拟内存的最大容量是由计算机的地址结构(CPU寻址范围)确定的
          2. 虚拟内存的实际容量 = min(内存和外存容量之和,CPU寻址范围)

          例:某计算机地址结构为32位,按字节编址,内存大小为512MB,外存大小为2GB.
          1. 虚拟内存的最大容量为232 B = 4GB
          2. 虚拟内存的实际容量 = min(512MB+2GB,232 )= 512MB+2GB

          扫描二维码关注公众号,回复: 12670223 查看本文章
        3. 虚拟内存的特征:
          1. 多次性:无需在作业运行时一次性全部装入内存,而是允许被分成多次调入内存
          2. 对换性:在作业运行时无需一直常驻内存,而是允许作业在运行过程中,将作业换入、换出
          3. 虚拟性:从逻辑上扩充了内存的容量,使用户看到的内存容量,远大于实际的容量
      4. 如何实现虚拟内存技术

        虚拟内存技术,允许一个作业分多次调入内存。如果采用连续分配方式,会不方便实现。因此,虚拟内存的实现需要建立在离散分配的内存管理方式基础上

        1. 传统的非连续分配存储管理:基本分页存储管理、基本分段存储管理、基本段页式存储管理
        2. 改进后的虚拟内存的实现:请求分页存储管理、请求分段存储管理、请求段页式存储管理
        3. 主要区别:
          1. 请求调页)在程序执行过程中,当所访问的信息不在内存中,由操作系统负责将信息从外存调入内存,然后继续执行程序
          2. 页面置换)若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存
      5. 请求分页管理方式

        1. 页表机制
          1. 与基本分页中页表的区别:
            1. 与基本分页管理相比,请求分页管理中,为了实现“请求调页”,操作系统需要知道每个页面是否已经调入内存;如果还没调入,那么也需要知道该页面在外存中存放的位置
            2. 当内存空间不够时,要实现“页面置换”,操作系统需要通过某些指标来决定到底换出哪个页面;有的页面没有被修改过,就不用再浪费时间写出外存了。有的页面修改过,就需要将外存中的旧数据覆盖,因此,操作系统也需要记录各个页面是否被修改的信息
          2. 请求分页中的页表: 在这里插入图片描述
        2. 缺页中断机制
          1. 过程:
            1. 假设此时要访问逻辑地址=(页号,页内偏移量)=(0,1024)
            2. 在请求分页系统中,每当要访问的页面不在内存时,便产生一个缺页中断,然后由操作系统的缺页中断处理程序处理中断
            3. 此时缺页的进程阻塞,放入阻塞列表,调页完成后再将其唤醒,放回就绪队列
            4. 如果此时内存有空闲块,则为进程分配一个空闲块,将所缺页面装入该块,并修该页表中相应的页表项
            5. 如果内存中没有空闲块,则由页面置换算法选择一个页面淘汰,若该页面在内存期间被修改过,则要将其写回内存未修改过的页面不用写回内存
          2. 缺页中断是因为当前执行的指令想要访问的目标页面为调入内存而产生的,因此属于内中断(信号来源于CPU内部,又因为是由错误条件引起的,可能被故障处理程序修复,所以归为内中断中的故障
          3. 一条指令在执行期间,可能产生多次缺页中断。(如:copy A toB,而A、B可能属于不同的页面,则有可能发生两次中断)
        3. 地址变换机构
          1. 基本分页与请求分页的主要区别
            1. 在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所有信息从外存调入内存,然后继续执行程序。
            2. 若空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存
          2. 新增步骤
            1. 请求调页(查到页表项是进行判断)
            2. 页面置换(需要调入页面,但没有空闲内存块时进行)
            3. 需要修改请求页表中新增的表项
          3. 过程:
            在这里插入图片描述
          4. 补充细节
            1. 只有==“写指令”才需要修改“修改位”==。并且,一般来说只需要修改快表中的数据,只有将快表项删除时才需要写回内存中的慢表。这样可以减少访存次数
            2. 和普通中断处理一样,缺页中断也需要保留CPU现场
            3. 需要用某种“页面置换算法”来决定一个换出页面
            4. 换入/换出页面都需要启动慢速的I/O操作,可见,如果换入/换出太频繁,会有很大开销
            5. 快表中的页面一定是在内存中的:如果有页面被换出外存,则快表中相应的页表项也要删除,否则可能访问错误的页面
            6. ⭐页面调入内存后,需要修改慢表,同时也要将表项直接复制到快表当中,这样若发生缺页,则地址变换步骤是:查快表(未命中)→查慢表(发现未调入内存)→调页(调入的页面对应的表项会直接加入快表)→查快表(命中) →访问目标内存单元
      6. ⭐页面置换算法

        页面的换入/换出需要磁盘I/O,会有较大的开销,因此好的页面置换算法应该追求更好的缺页率

        1. 最佳置换算法(OPT)

          1. 思想:每次选择淘汰的页面将是以后永远不使用,或者在最长时间内不再被访问的页面,这样就可以保证最低的缺页率
          2. 例: 在这里插入图片描述
          3. 算法性能:
            1. 整个过程中缺页中断发生9次,页面置换发生6次。(并不是发生缺页就会有页面置换,只有在内存已满时才会换入换出)
            2. 缺页率 = 9 / 20 = 45%
            3. 最佳置换算法需要知道之后需要访问的是哪个页面,但实际上,操作系统是无法预料页面访问序列的,故,最佳置换算法是无法实现的
        2. 先进先出置换算法(FIFO)

          1. 思想:每次选择置换的页面是最早调入内存的页面
          2. 实现方法:把调入内存的页面根据调入的先后顺序排成一个队列,需要换出页面时选择队头页面即可。队列最大长度取决于系统为进程分配了多少内存块
          3. 例1:分配三个内存块时,缺页次数:9次 在这里插入图片描述
          4. 例2:分配四个内存块时,缺页次数:10次 在这里插入图片描述
          5. belady异常:
            1. 当为进程分配的物理块数增大时,缺页次数不减反增的现象
            2. 只有FIFO算法会产生belady异常
            3. 虽然FIFO算法实现简单,但该算法与进程实际运行时的规律不适应,因为先进入的页面也有可能被最经常访问,若总是换出先入的页面(简单粗暴),导致算法性能不高
        3. 最近最久未使用置换算法(LRU)

          1. 思想:每次淘汰的页面是最近最久未使用的页面
          2. 实现方法:赋予每个页面对应的页表项中用访问字段记录该页面至上次被访问以来所经历的时间 t 当需要淘汰一个页面时,选择 t 值最大的页面换出
          3. 例: 在这里插入图片描述
          4. 动手做题时,若需要淘汰页面,逆向数最后出现的,就是要淘汰的
          5. 算法性能
            1. 算法性能好,最接近最佳置换算法
            2. 但是实现困难,需要专门的硬件支持,开销比较大
        4. 时钟置换算法(CLOCK)

          1. 思想:一种性能和开销较为均衡的算法,又称CLOCK算法,或最久未用算法NRU
          2. 实现方法 :为每一个页面设置一个访问位,再将内存中的页面全都用链接指针连接成一个循环队列。
            1. 当某页被访问时,将其访问位置为1
            2. 当需要淘汰一个页面时,开始扫描,只需要检查页的访问位。
              1. 如果是0,就选择该页换出;如果是1,则将它置为0,暂时不换出,继续检查下一个页面,
              2. 若第一轮扫描中所有页面都是1,则将这些页面的访问位依次置为0后(第一轮中边扫边置0),进行第二轮扫描(第二轮中一定会有页面的访问位是0,故CLOCK算法中选择一个淘汰页面最多会经过两轮扫描)
          3. 例子:假设系统为某进程分配了五个内存块,并考虑到有以下页面号引用串:1、3、4、2、5、6、3、4、7
            1. 访问6号页之前:1号页(1),3号页(1),4号页(1),2号页(1),5号页(1)
            2. 访问到6号页:6号页不再内存中,需要换出一页,开始扫描此时扫描指针指向1号页
              1. 第一轮扫描:1号页(0),3号页(0),4号页(0),2号页(0),5号页(0)此时扫描指针指回了1号页
              2. 第二轮扫描:6号页(1),3号页(0),4号页(0),2号页(0),5号页(0)此时扫描指针指向下一个页面,即3号页
            3. 访问到3号页:6号页(1),3号页(1),4号页(0),2号页(0),5号页(0)
            4. 访问到4号页:6号页(1),3号页(1),4号页(1),2号页(0),5号页(0)
            5. 访问到7号页:7号页不再内存中,需要换出一页,开始扫描
              1. 第一轮扫描(从3号页开始扫描):6号页(1),3号页(0),4号页(0),7号页(1),5号页(0) 此时扫描指针指向下一个页面,即5号页
        5. 改进型的时钟置换算法

          1. 思想:之前学过,若被换出的页面没有被修改过,则不需要执行I/O操作写回外存,只有被修改过的页面才需要写回外存
          2. 因此,除了考虑一个页面是否被访问过之外,还需要考虑被访问的页面是否被修改
          3. 实现方法:再设置一个修改位,=1时表示修改过、=0时表示未修改;则利用二元组:==(访问位,修改位)==标识一个页面
          4. 算法规则:将所有可能被置换的页面排成一个循环队列
            1. 第一轮:将当前位置开始扫描到第一个(0,0)的帧用于替换。本轮扫描不修改任何标志位
            2. 第二轮:若第一轮扫描寻找失败,则重新扫描,查找第一个(0,1)的帧用于替换。本轮将所有扫描过的页面的访问位设置为0
            3. 第三轮:若第二轮扫描寻找失败,则重新扫描,查找第一个(0,0)的帧用于替换。本轮扫描不修改任何标志位
            4. 第四轮:若第三轮扫描寻找失败,则重新扫描,查找第一个(0,1)的帧用于替换。
          5. 由于第二轮中会将所有访问位设置为0,故在第三轮或第四轮中一定回找到目标页面。故扫描次数一定不会超过四轮
          6. 扫描置换优先级:
            1. 第一轮:最近未访问,且没修改的页面
            2. 第二轮:最近未访问,且修改过的页面
            3. 第三轮:最近访问过,且没修改的页面
            4. 第四轮:最近访问过,且修改过的页面
        6. ⭐页面置换算法的比较: 在这里插入图片描述

      7. 页面分配策略

  3. 3. 操作系统需要提供地址转换功能

    负责程序的逻辑地址与物理地址的转换

    三种装入方式

  4. 4. 操作系统需要提供内存保护功能

    保证各个进程在各自的存储空间内运行,互不干扰 在这里插入图片描述
    内存保护可采取的两种方法:

    1. 方法一:在CPU中为每个进程设置一对上下限寄存器,存放进程的上下限地址。当进程的一条指令需要访问数据时,会检查该指令访问的数据地址是否在该指令所属的进程的地址上下限中,即是否越界
      在这里插入图片描述
    2. 方法二:采用重定位寄存器(又称基址寄存器)和界地址寄存器(又称限长寄存器)进行越界检查。重定位寄存器中存放的时进程的 起始物理地址,界地址寄存器存放的是进程的 最大逻辑地址
      在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Qmilumilu/article/details/113739306