操作系统之内存管理

最近对操作系统的内存管理比较感兴趣,所以重学了一下内存管理(参考王道操作系统)
也可以直接看我的笔记:点击访问

内存的基本概念

存储单元的编址方式

  1. 按字节编址,每个存储单元大小为1B
  2. 按字编址,每个存储单元大小为1个字,具体字长看计算机

逻辑地址和物理地址

  • 逻辑地址:又叫相对地址,用于表示程序在内存中的相对位置
  • 物理地址:又叫绝对地址,即程序在内存中的真实地址

一个程序装入内存的步骤

  1. 源代码编译为目标代码
  2. 链接(多个目标代码以及所需库函数需要链接在一起成为装入模块,装入模块的地址一般从0开始),这时有了完整的逻辑地址
  3. 装入程序将装入模块装入内存,这时才有物理地址

目标代码装入内存的3种方式(逻辑地址转换为物理地址的3种方式)

  1. 绝对装入:编译链接时就确定了物理地址,灵活性低,只适用于单道程序环境
  2. 静态重定位:由装入程序负责逻辑地址到物理地址的转换
  3. 动态重定位:程序真正被执行时才进行地址转换,所以需要一个重定位寄存器,也叫基址寄存器。动态重定位的好处:允许程序在内存中移动,允许程序分配到不连续的内存

多个目标模块链接的3种方式

  1. 静态链接:在程序运行之前链接成一个完整的可执行模块,具有完整的逻辑地址
  2. 装入时动态链接:一边装入内存,一边链接
  3. 运行时动态链接:程序执行过程中需要某个目标模块时,才进行链接

操作系统如何保证各个进程在各自存储空间内运行?(内存保护)

  1. 设置上、下限寄存器
  2. 设置基址寄存器、界地址寄存器,进行越界检查

内部碎片和外部碎片

  • 内部碎片:分配给进程的内存空间中空闲的部分
  • 外部碎片:整个内存中空闲的部分

覆盖和交换技术

  • 覆盖和交换都用于解决程序大小超过内存大小的问题

覆盖

  • 只存在于早期的OS,不用了解了

交换

  • 在内存紧张时,将某些进程暂时换出到外存,将外存中具备运行条件的进程换入内存
  • 中级调度,即内存调度
  • 在具备交换功能的OS中,一般将磁盘分为文件区和交换区,文件区追求存储空间利用率,交换区追求交换速度,所以交换区的IO速度一般比文件区快
  • 注:PCB不会被换出内存
    在这里插入图片描述

内存空间的3种连续分配方式

  • 连续分配:进程必须分配连续的存储空间
  • 已经过时

单一连续分配

  • 内存被分为系统区和用户区,只能有一个用户进程
  • 优点:实现简单,无外部碎片
  • 缺点:只能用于单用户、单进程的OS,有内部碎片

固定分区分配

  • 在单一连续分配的基础上,将用户区分为多个分区(大小不一定相等),每个分区只能装入一个作业
  • 这是最早的可运行多道程序的内存管理方式
  • 需要维护一个分区说明表,每个表项包括:分区号、大小、起始地址、是否分配
  • 优点:实现简单,无外部碎片
  • 缺点:分区大小固定;有内部碎片

动态分区分配

  • 不会预先划分分区,而是在进程装入内存时根据进程大小动态建立分区
  • 同样需要维护一个空闲分区表/链,当进程装入、进程结束时要对其进行调整
  • 当多个空闲分区都能满足需求时,如何选择,这涉及动态分区分配算法
  • 优点:没有内部碎片
  • 缺点:有外部碎片(可通过紧凑技术解决)

动态分区分配算法

  • 用于在多个满足条件的空闲分区中选择一个分区来装入
首次适应算法(first fit)
  • 空闲分区表按地址递增排列,选择第一个满足大小的分区
  • 缺点:导致低地址部分产生较多小碎片
邻近适应算法(next fit)
  • 和首次适应算法类似,但每次查找时从上次查找结束的位置开始,而不是从头开始,这样就避开了低地址部分的碎片
  • 缺点:导致无论低地址高地址的空闲分区都有相同概率被使用,最后就没有较大的空闲分区了
最佳/小适应算法(best fit)
  • 空闲分区表按容量递增排列,选择第一个满足大小的分区(也就是优先使用更小的空闲区)
  • 缺点:会产生很多很小的外部碎片
最坏/大适应算法(worst fit)
  • 与最佳适应算法相反,空闲分区表按容量递减排列
  • 缺点:导致较大的空闲分区很快就用完,之后有大进程装入时,就没有可用分区了

内存空间的3种非连续分配方式

  • 连续分配的缺点很明显:不管怎样都会产生内存碎片,且进程必须连续存储

基本分页存储管理

  • 将内存分为大小相等的分区,每个分区只占很小的内存,如4KB,称为页框页帧物理块内存块,页框号从0开始
  • 同时,进程的地址空间也分为和页框大小相等的区域,称为页面,页号也从0开始
    • 每个页的起始地址存在页表中,每个进程都会维护一个页表
  • 一个进程的页在内存中不需要连续存储
  • CPU需要2次访问内存:查页表、访问最终物理地址

分页存储如何实现逻辑地址到物理地址的转换?

  1. 求逻辑地址对应的页号
  2. 从页表获取该页号对应页面在内存的起始地址
  3. 求逻辑地址在页面内的偏移量
  4. 物理地址 = 页面始址 + 页内偏移量

比如逻辑地址=80,页面长度=50,那么页号=80/50=1,偏移量=80%50=30,物理地址=30+第1页的起始地址


一般来说,页面大小为2的整数幂,这是为了方便计算机运算

  • 逻辑地址的结构由页号+页内偏移量组成
  • 如果一个页的大小为 2 K 2^K 2K个内存单元,那么就有K位表示偏移量
  • 而一个进程最多允许有 2 M 2^M 2M个页面,对应M位页号

页表的组成

  • 页表项由页号+页框号组成
  • 通过页表计算某一页的物理起始地址=对应页框号*页框大小

基本分页地址变换机构

  • 页表寄存器PTR页表起始地址、页表长度(即有多少个页表项)组成
  • 当进程未执行时,页表起始地址和页表长度放在PCB中,当进程被运行时,就会被加载到PTR
  • 下图是基本地址变换机构将逻辑地址转化为物理地址的过程:

在这里插入图片描述

具有快表的地址变换机构

  • 局部性原理
    • 时间局部性:某条指令或数据被访问后,不久之后,很可能会再次被访问
    • 空间局部性:某个存储单元被访问后,不久之后,其附近的存储单元也很可能被访问
  • 快表就利用了局部性原理
  • 快表其实就是页表的一部分副本(存放最近访问过的页表项),快表属于高速缓存,命中快表后,CPU只需要1次内存访问(由于局部性原理,命中率可以达到90%以上);快表满了后需要根据页面置换算法对旧的页表项进行替换

两级页表

  • 单级页表存在的问题:
    1. 需要分配连续的页框来存放页表,如果页表很大,就会占用很多连续页框
    2. 整个页表需要常驻内存
  • 解决第1个问题:
    • 将页表项分组,每个分组大小刚好占用一个页框,分组可以离散存储。然后为这些分组建立一张页表,称为页目录表,或称外层页表
    • 此时逻辑地址将由3部分组成:一级页号+二级页号+页内偏移量
  • 解决第2个问题:
    • 在需要访问某个页时才将其调入内存(虚拟内存技术
    • 在页表项中增加一个标志,表示该项是否在内存中,如果访问的页不在内存,则产生缺页中断,然后将其调入内存

n级页表的缺点:需要n+1次访问内存(一级页表 + 二级页表 + ··· + 最终物理地址)

基本分段存储管理

  • 分段,和分页差不多,将某个进程划分为多个大小不等的段,每个段可以离散存储
  • 需要维护一个段表,段表项包括:段号(隐含)、段长、段基址
  • GDTR寄存器(48位),用于存储当前段表项:段上限(段长) + 段的起始地址,通过LGDT指令给该寄存器赋值
  • 分段和单级页表一样,也需要2次访存:访问段表+最终物理地址
  • 分段也可以使用快表提高访问速度
  • 分段存储地址转换过程如下:

在这里插入图片描述

分页和分段的比较

  • 分页的目的是提高内存利用率,并实现离散存储,页是一个物理单位,分页是系统行为,用户不可见
  • 分段的目的是满足用户需求,一个段通常包含属于一个逻辑模块的信息,段是逻辑单位,对用户是可见的
  • 分段更容易实现信息共享、保护
  • 分段会产生外部碎片

段页式存储管理

  • 段页式存储综合了分页和分段的优点
  • 段页式存储的逻辑地址结构:段号 + 页号 + 页内偏移量
    • 段号位数决定了每个进程最多可以分几个段
    • 页号位数决定了每个段最多有多少个页
    • 偏移量位数决定了页的大小
  • 每个进程都要维护一个段表,段表项包含:段号(隐含)、页表长度(有多少个页)、页表起始地址
  • 然后页表项包含:页号、页框号
  • 也就是说,一个进程要维护一个段表 + 多个页表
  • CPU需要3次访存:访问段表、访问页表、最终物理地址
  • 段页式存储同样可以引入快表
  • 段页式存储的地址转换过程:

在这里插入图片描述

虚拟内存技术

虚拟内存基本概念

  • 当进程开始运行时,先将一部分程序装入内存,另一部分暂时留在外存;当要执行的指令不在内存时,由系统自动完成将它们调入内存的工作;当没有足够的内存时,系统自动选择部分内存(暂不执行的程序)空间,将其中原有的内容交换到磁盘上,并释放这些内存空间供其他进程使用
  • 这样做的结果使程序的运行丝毫不受影响,使程序在运行中感觉到拥有一个不受内存容量约束的、虚拟的、能够满足自己需求的存储器

  • 虚拟内存的最大容量:由计算机的地址结构(CPU寻址范围)决定,而实际容量为min(内外存总容量,CPU寻址范围)
    • 比如某计算机地址结构为32位,按字节编址,内存=512MB,外存=2GB,那么最大容量= 2 32 2^{32} 232B=4GB,实际容量=min(4GB,512MB+2GB)

  • 虚拟内存技术是建立在非连续分配存储的基础上的,主要区别在于:
    1. 增加了请求调页(调段)功能(用于缺页时换入)
    2. 增加了页置换(段置换)功能(用于内存不够时换出)
  • 因此,相应的,虚拟内存技术分为3种实现:
    1. 请求分页存储管理
    2. 请求分段存储管理
    3. 请求段页式存储管理

虚拟内存的页表机制

  • 虚拟内存中的页表称为请求页表,页表项包括:
    • 页框号
    • 状态位:是否已经调入内存
    • 访问字段:最近被访问过几次、上次访问时间(供置换算法换出页面时参考)
    • 修改位:该页调入内存后是否被修改(未修改则不需要写回外存)
    • 外存地址

缺页中断机构的原理

  • 在请求分页系统中,每当所要访问的页面不在内存时,便产生一个缺页中断,OS调用缺页中断处理程序,此时缺页的进程阻塞,进入阻塞队列,调页完成后再唤醒,进入就绪队列
  • 若内存中有空闲块,则分配一个块,将所缺页装入该块,并修改页表中相应页表项
  • 若此时内存中没有空闲块,则页面置换算法选择某个页面淘汰,若被淘汰页在内存期间被修改过,则要将其写回外存

  • 内中断和外中断的区别
    • 内中断:中断信号源于CPU内部,如缺页中断、系统调用
    • 外中断:中断信号源于CPU外部,如IO中断、键盘中断

虚拟内存页面置换算法

  • 终于来到页面置换算法了😄
  • 页面换入换出是IO操作,好的置换算法应该追求更少的缺页率

最佳置换算法(OPT)——简称:不可能的算法

  • 最佳 (Optimal, OPT) 置换算法所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率
  • 但由于目前无法预知哪个是未来最长时间内不再被访问的页面,因而该算法无法实现
  • 但最佳置换算法可以用来评价其他算法

先进先出置换算法(FIFO)

  • 优先淘汰最早进入内存的页面,亦即在内存中驻留时间最久的页面。该算法实现简单,只需把调入内存的页面根据先后次序链接成队列,设置一个指针总指向最早的页面。
  • FIFO算法会产生当进程所分配的物理块数增大而缺页率不减反增的异常现象,这是由 Belady 于1969年发现,故称为 Belady 异常只有 FIFO 算法可能出现 Belady 异常,而 LRU 和 OPT 算法永远不会出现 Belady 异常

最近最久未使用置换算法(LRU)

  • 选择最近最长时间未访问过的页面予以淘汰,它认为过去一段时间内未访问过的页面,在最近的将来可能也不会被访问
  • OS会参考请求页表项中的访问字段
  • LRU 性能较好,但需要寄存器和栈的硬件支持。LRU 是堆栈类的算法。理论上可以证明, 堆栈类算法不可能出现 Belady 异常。FIFO 算法基于队列实现 ,不是堆栈类算法。

时钟置换算法(CLOCK)

  • 该算法将页表项链接成一个循环队列,循环检查各页面的情况,像时钟的针一样转动,所以叫CLOCK算法,又称为最近未用(Not Recently Used, NRU)算法
  • 步骤:循环扫描,第一轮淘汰访问位=0的页,若扫描过的页的访问位=1,将其置为0,暂不换出。若未找到,则进行第二轮
  • 最多2轮扫描

改进型的时钟置换算法

  • 增加了修改位,用(访问位,修改位)来表示页面状态
  • 这是因为要优先淘汰没有访问过且没有修改过的页,这样就不用IO写出外存
  • 该算法最多扫描4轮,步骤如下:

在这里插入图片描述

页面和页框的补充知识

驻留集

  • 驻留集就是OS分配给一个进程的页框的集合
  • 驻留集一般小于进程总大小
  • 驻留集太小,会导致缺页频繁,太大,会导致多道程序并发度下降
  • 一般来说,驻留集大小不能小于工作集大小,否则会频繁缺页

工作集

  • 指在某个窗口尺寸内,进程实际访问页面的集合
  • 工作集大小一般小于窗口大小

页框分配策略、页面置换策略

  • 固定分配:驻留集大小不变
  • 可变分配:驻留集大小可变
  • 局部置换:进程缺页时只能选自己的驻留集中的空闲页框置换
  • 全局置换:进程缺页时可以选其他进程的空闲页框置换

  • 不存在固定分配+全局置换的组合,其他组合都是可以的
  • 可变分配+局部置换的综合性能更好

调页策略

  • 预调页策略:进程首次运行前调入一些相邻的页
  • 请求调页策略:即运行时缺某个页才调页

抖动现象

  • 抖动是指某些页面频繁的换入换出
  • 主要原因:分配给进程的物理块(页框) < 频繁访问的页数

参考

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值