【操作系统】2.内存管理

文章目录

  • 0.如何分配物理内存
  • 1. 连续内存分配
    • 1.1 计算机体系结构和内存分层体系
      • 基本硬件结构:
      • 操作系统对内存分配做了什么
      • 操作系统采用的内存管理方式
    • 1.2 地址空间和地址生成
    • 1.3 内存碎片和分区的动态分配
      • 内存碎片问题
      • 分区分配
      • 1.4 碎片整理
        • 压缩式碎片整理
        • 交换式碎片整理
  • 2. 非连续内存分配
    • 2.1 需求背景
      • 非连续内存空间的分配要解决的问题
    • 2.2 段式存储管理
      • 访问机制
    • 2.3 页式存储管理
    • 2.4 页表
    • 2.5 快表和多级页表
    • 2.6 反置页表
    • 2.7 段页式存储管理机制
  • 3.虚拟存储
    • 3.1 需求
    • 3.2 覆盖和交换
      • 覆盖
      • 交换
      • 覆盖与交换技术的比较
    • 3.3 局部性原理
    • 3.4 虚拟存储概念
    • 3.5 虚拟页式存储
    • 3.6缺页异常
  • 4.置换算法
    • 4.1 概念
    • 4.2 最优置换算法(OPT,Optimal replacement algorithm)
    • 4.3 先进先出(FIFO, First In First Out)
    • 4.4最近最久未使用(LRU, Least Recently Used)
    • 4.5 时钟置换算法(Clock)二次机会算法
      • 改进型的时钟置换操作
    • 4.6最不常用算法(LFU,least frequently used)
    • Belady现象
      • Belady现象
      • LRU、FIFO和Clock的比较
    • 4.6 全局置换算法
    • 4.7工作集置换算法
    • 4.8 缺页率置换算法:
    • 4.9抖动与负载控制:

0.如何分配物理内存

内存分成两部分:内核使用部分、用户使用部分,那么它们是否是平等的呢?

不平等,试想如果是平等的:那么我们可以随意修改内核所用的内存,那么系统岂不是乱套啦!
既然不平等,就要引入保护机制,防止恶意修改。

我们如何记录哪些内存已经分配/未分配呢?这些信息保存在哪里?

有以下几种物理内存分配方案:

  1. 分区存储管理
  2. 分页存储管理
  3. 多级页表管理
  4. 虚拟存储管理
  5. 分段存储管理

1. 连续内存分配

1.1 计算机体系结构和内存分层体系

基本硬件结构:

CPU(程序执行处),内存(放置了代码和处理的数据),设备(I/O)

操作系统对内存分配做了什么

(1)抽象,逻辑地址空间;
(2)保护,独立地址空间;
(3)共享,访问相同内存;
(4)虚拟化,更多的地址空间,对应用程序透明

操作系统采用的内存管理方式

  • 重定位:段地址+偏移
  • 分段:分成代码、数据、堆栈
  • 分页:把内存分成最基本的单位
  • 虚拟存储:把数据存到硬盘上,使得逻辑地址空间大于物理内存空间

1.2 地址空间和地址生成

物理地址空间:硬件支持的地址空间

逻辑地址空间:一个运行的程序所看到的内存空间

两者之间存在映射关系,最终执行时还是落在物理地址空间上。

源程序不能再计算机上直接被运行,需要通过三个阶段的处理:编译程序处理源程序并生成目标代码,链接程序把他们链接为一个可重定位代码,此时该程序处于逻辑地址空间中;下一步装载程序将可执行代码装入物理地址空间,直到此时程序才能运行。

可执行程序逻辑地址转换为物理地址的过程被称为 “地址重定位”。

逻辑地址是如何映射到物理地址:
CPU方面
1.运算器ALU需要在逻辑地址的内存内容(CPU要逻辑地址)
2.内存管理单元MMU寻找在逻辑地址和物理地址之间的映射(然后MMU找逻辑和物理地址的关系)
3.控制器从总线发送在物理地址的内存内容的请求(关系找到后,去找对应物理地址)
内存方面
4.内存发送物理地址内存内容给CPU(物理地址找到了,给CPU)
操作系统方面
5.建立逻辑地址和物理地址之间的映射(确保程序不相互干扰)

1.3 内存碎片和分区的动态分配

内存碎片问题

内存碎片:两个进程之间连续物理内存地址空间未使用的内存为内存碎片

外部碎片:在分配单元之间的未使用内存

内部碎片:在分配单元内部未使用的内存

分区分配

连续内存分配有两种实现方式:固定分区分配,动态分区分配

动态分区分配

  1. 动态分配下,按照作业大小来划分分区,但划分的时间、大小、位置都是动态的。系统把作业装入内存时,根据其所需要的内存容量查看是否有足够空间,若有则按需分割一个分区分配给此作业;若无则令此作业等待内存资源。
  2. 操作系统需要维护的数据结构:所有进程的已分配区以及空闲分区
  3. 动态内存分配策略:

最先匹配(地址优先):从0地址往后查找和使用第一个可用空闲快

最佳匹配(空闲分区大小优先):找比需求大但最接近需求的空闲内存块,产生尽可能小的内存碎片。

最差匹配(最大空闲分区优先):使用最大的空闲块。

1.4 碎片整理

碎片整理:通过调整进程占用的分区位置来减少或避免分区碎片。

压缩式碎片整理

使用条件:所有的应用程序可以动态重定向。
调整内存中程序运行的位置,通过拷贝尽量把程序放到一起,空出较多的空闲位置。

交换式碎片整理

外存(swap分区)当做内存的备份,把在等待的进程包括数据放在外存上,腾出空间给其余运行的进程(抢占等待进程,回收其内存),这个方法也要考虑开销和换哪个进程。

2. 非连续内存分配

2.1 需求背景

  1. 连续分配物理地址必须连续,存在碎片,动态修改困难,导致内存利用率极低。
  2. 非连续内存分配可提高内存利用效率和管理灵活性。
    1. 允许一个程序使用非连续的物理地址空间。
    2. 允许共享代码和数据
    3. 支持动态加载(进程在内存中大小是动态)和动态链接

非连续内存空间的分配要解决的问题

  1. 如何实现虚拟地址和物理地址的转换
    1. 软件实现(灵活,开销大)
    2. 硬件实现(够用,开销小)
  2. 如何选择非连续分配中的内存分块大小
    1. 段式存储管理(segmentation)
    2. 页式存储管理(paging)

2.2 段式存储管理

把逻辑地址空间分散到多个物理地址空间,堆→堆,运行栈→运行栈,程序数据→数据,运行exe→代码和库

逻辑地址空间是连续的,物理地址是离散的,每个段的逻辑地址都由段号s和段内偏移addr构成。

段内要求连续,段间不一定连续,故整个进程的地址空间是二维的。

【操作系统】2.内存管理_第1张图片

访问机制

首先用段号查段表,里面有它的起始地址和长度,由操作系统控制。

MMU检查addr偏移是否大于段的长度,合法就用段基址+偏移得到实际的物理地址

2.3 页式存储管理

分页也是实现机制和寻址,也需要页号和偏移,区别在于页帧的size不变。

  1. 页帧
    1. 物理地址空间划分为大小相同的基本分配单位,是2^n;
    2. 二元组(帧号,帧内偏移)
  2. 页面
    1. 逻辑地址空间划分为相同大小的基本分配单位
    2. 页面的大小和页帧必须是相同的。
    3. 二元组(页号, 页内偏移)
  3. 页面到页帧的转换关系
    1. 实际上就是逻辑地址到物理地址的转换
    2. 页表 每个进程都有一个页表,页表里面的内容是动态变化的,逻辑地址空间通过页表查找对应的物理地址空间
      【操作系统】2.内存管理_第2张图片

2.4 页表

  1. 每一个进程都有一个页表
    1. 每个页面对应一个页表项
    2. 随进程运行状态而动态变化
    3. 页表存储在页表基指寄存器PTBR
  2. 页式存储管理机制的性能问题
    1. 内存访问性能降低,访问一个内存单元需要2次内存访问:一次获取页表项;一次是访问数据。
    2. 页表可能非常大(页表的长度等于2^页号位数)
  3. 解决方案
    1. 缓存,缓存近期访问的页帧转换表项。
    2. 间接访问

2.5 快表和多级页表

【操作系统】2.内存管理_第3张图片

快表(TLB):通过缓存技术解决内存访问性能问题,缓存近期访问的页表项,使用关联存储实现,具备快速访问。快表命中率可达90%

【操作系统】2.内存管理_第4张图片

多级页表:通过间接访问技术解决内存访问性能问题,后一级页表大小对应前一级需要存储的地址大小,形成树状结构,由于进程不会使用到所有的页表,故可以减小页表大小.增加了内存访问次数和开销,但是节省了保存页表的空间。

2.6 反置页表

反置页表:大地址空间,多级页表很繁琐。

2.7 段页式存储管理机制

段式存储在内存保护方面有优势,页式存储在内存利用和优化转移到后备存储方面有优势。结合段式存储和页式存储。

通过指向相同的页表基址,可实现进程间的段共享。

【操作系统】2.内存管理_第5张图片

【操作系统】2.内存管理_第6张图片

3.虚拟存储

虚拟存储是在非连续存储基础上把一部分数据放在外存里边。可以得到更大的内存存储空间,且保持可观的访问速度。

3.1 需求

经常出现内存不够了。程序规模的增长大于存储器容量的增长。
【操作系统】2.内存管理_第7张图片

3.2 覆盖和交换

覆盖

目标:在较小的可用内存中运行较大的程序。常用于多道程序系统,与分区存储管理配合使用。

原理:按自身逻辑把程序分成几个功能上相对独立的模块,不会同时执行的模块可以共享同一块内存区域,按时间先后运行(分时)。

【操作系统】2.内存管理_第8张图片

缺点:
(1) 设计开销,程序员要划分模块和确定覆盖关系,编程复杂度增加了
(2) 覆盖模块从外存装入内存,实际是以时间来换空间。

交换

目标:多道程序在内存中时,让正在运行的程序或需要运行的程序有更多的内存资源。

方法:可将暂时不能运行的程序送到外存以获得空闲内存空间,操作系统在内存管理单元MMU帮助下把一个进程的整个地址空间的内容保存到外存中(换出swap out),而将外存中的某个进程的地址空间读入到内存中(换入swap in)。其大小为整个程序的地址空间(比较大,几十几百个页)。

交换技术实现中的几个问题

  1. 交换时机的确定:只有当内存空间不够或有不够的危险时换出
  2. 交换区的大小:必须足够大以存放所有用户进程的所有内存映像的拷贝,必须能对这些内存映像进行直接存取
  3. 程序换入时的重定位:因为换出换入后的内存位置不一定相同,所以最好采用动态地址映射的方法

覆盖与交换技术的比较

覆盖只能发生在那些(程序内)相互之间没有调用关系的程序模块之间,因此程序员必须给出程序内的各个模块之间的逻辑覆盖结构。

交换技术是以在内存中进程为单位来进行的,它不需要程序员给出各个模块之间的逻辑覆盖结构。

交换发生在内存中进程与管理程序或操作系统之间,而覆盖则发生在运行程序的内部模块之间。

3.3 局部性原理

局部性原理是根据程序的特点分析出的几条特征,比如一个数据的两次访问很可能集中在比较短的时间内,当前访问的数据邻近的数据很可能马上也会被邻近的指令访问。

局部性原理:程序在执行过程中的一个较短时期,所执行的指令地址和指令的操作数地址,分别局限于一定区域。

  1. 时间局限性:一条指令的一次执行和下次执行,一个数据的一次访问和下次访问都集中在一个较短时期内。
  2. 空间局部性:当前指令和邻近的几条指令,当前访问的数据和邻近的几个数据都集中在一个较小的区域内。
  3. 分支局部性:一条跳转指令的两次执行,很可能跳到相同的内存位置。

3.4 虚拟存储概念

思路:将不常用的部分内存块暂存到外存。

原理:

  1. 装载程序时:只将当前指令执行需要的部分页面或段装入内
  2. 指令执行中需要的指令或数据不在内存(缺页或缺段)时:处理器通知操作系统将相应的页面或者断调入内存。(用的时候再装)
  3. 操作系统将内存中暂时不用的页面或者段保存到外存中

实现方式:

  1. 虚拟页式存储
  2. 虚拟段式存储

虚拟存储的基本特征

  1. 不连续性:物理内存分配非连续,虚拟地址空间使用非连续
  2. 大用户空间:提供给用户的虚拟内存可大于实际的物理内存
  3. 部分交换:虚拟内存只对部分虚拟地址空间进行调入和调出

3.5 虚拟页式存储

思路:

  1. 当用户程序要装载到内存运行时,只装入部分页面,就启动程序运行
  2. 进程在运行中发现有需要的代码或数据不在内存时,则向系统发出缺页异常请求。
  3. 操作系统在处理缺页异常时,将外存中相应的页面调入内存使得进程能够继续运行。

页表项增加了:驻留位,修改位,保护位,访问位

  • 驻留位:表示是否在内存,不在则出现缺页异常
  • 修改位:表示是否被修改过
  • 保护位:表示是否可读、可写
  • 访问位:表示是否被访问过,用于置换算法

3.6缺页异常

逻辑地址查找页表对应的页表项不存在,需要在外存中寻找页面并修改页表项。若页表项驻留位为0,则产生缺页异常,执行缺页异常服务程序

4.置换算法

4.1 概念

置换算法的功能:当出现缺页时,需要调入新页面但是内存已满时,置换算法用于选择被置换的物理页面(从内存中拿走一个,从外存中拿进来一个);

目标:尽可能减少页面的换入换出次数。把未来不再使用的或短期内较少使用的页面换出,通常只能在局部性原理的指导下依据过去的统计数据来进行预测。

页面锁定(frame locking):用于描述必须常驻内存的操作系统的关键部分或时间关键(time-critical)的应用进程。实现方法是,在页表中添加锁定标志位(lock bit)。

置换算法可以分为两类:局部页面置换算法和全局页面置换算法。

局部页面置换算法:置换页面的选择范围仅限于当前进程占用的页面内。

具体实现:最优算法,先进先出算法、最近最久未使用算法、时钟算法,最不常用算法。

全局页面置换算法:置换页面的选择范围是所有可换出的物理页面(可以置换其他进程的页面)

具体实现:工作集算法、缺页率算法

4.2 最优置换算法(OPT,Optimal replacement algorithm)

  • 算法实现:缺页时计算内存中每个逻辑页面的下一次访问时间
  • 置换最长时间不被访问的页面
  • 这种方法是理想的,操作系统不可实现,因为不知道下次访问时间
  • 可作为置换算法的性能评价依据

举例:一个系统为某进程分配了三个物理块,并有如下页面引用序列:

7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1

开始运行时,先将 7, 0, 1 三个页面装入内存。当进程要访问页面 2 时,产生缺页中断,会将页面 7 换出,因为页面 7 再次被访问的时间最长。

例题:物理页帧数量为3,虚拟页访问序列为 0,1,2,0,1,3,0,3,1,0,3,请问采用最优置换算法的缺页次数为(4)

插入顺序 0 1 2 0 1 3 0 3 1 0 3
内存 0 0 0 0 0 0 0 0 0 0 0
内存 1 1 1 1 1 1 1 1 1 1
内存 2 2 2 3 3 3 3 3 3
是否缺页

【操作系统】2.内存管理_第9张图片

4.3 先进先出(FIFO, First In First Out)

选择在内存驻留时间最长的页面进行置换

实现:维护一个记录所有内存中的逻辑页面链表

链表元素按驻留内存的时间排序,链首最长,链尾最短,出现断页时,选择链首页进行置换,新页面加到链尾

特征:
i. 性能较差,实现简单,调出的页面可能是经常访问的
ii. 进程分配物理页面数增加时,缺页并不一定减少
iii. 很少单独使用。

例题:物理页帧数量为3,虚拟页访问序列为 0,1,2,0,1,3,0,3,1,0,3,请问采用LRU置换算法的缺页次数为(6)

插入顺序 0 1 2 0 1 3 0 3 1 0 3
内存 0 0 0 0 0 3 3 3 3 3 3
内存 1 1 1 1 1 0 0 0 0 0
内存 2 2 2 2 2 2 1 1 1
是否缺页

【操作系统】2.内存管理_第10张图片

【操作系统】2.内存管理_第11张图片

4.4最近最久未使用(LRU, Least Recently Used)

选择最长时间没有被引用的页面进行置换,如果某些页面长时间未被访问,则它们在将来还可能长时间不会访问。

实现:为了实现 LRU,需要在内存中维护一个所有页面的链表或者栈。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面是最近最久未访问的。

特征:最优置换算法的一种近似,每次访问都需要更新链表,因此这种方式实现的 LRU 代价很高。

4,7,0,7,1,0,1,2,1,2,6

放6的时候将4置换

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qqHMl47Z-1592879546095)(https://camo.githubusercontent.com/88a3ea6558a8b9326f6fd95d74b2ff07625427b5/68747470733a2f2f63732d6e6f7465732d313235363130393739362e636f732e61702d6775616e677a686f752e6d7971636c6f75642e636f6d2f65623835393232382d633066322d346263652d393130642d6439663736393239333532622e706e67)]

例题:物理页帧数量为3,虚拟页访问序列为 0,1,2,0,1,3,0,3,1,0,3,请问采用LRU置换算法的缺页次数为(4)

插入顺序 0 1 2 0 1 3 0 3 1 0 3
内存 0 0 0 0 0 0 0 0 0 0 0
内存 1 1 1 1 1 1 1 1 1 1
内存 2 2 2 3 3 3 3 3 3
是否缺页

4.5 时钟置换算法(Clock)二次机会算法

仅对页面的访问情况进行大致统计,是LRU和FIFO的折中。

数据结构

i. 在页表中增加访问位,描述页面在过去一段时间的内存访问情况
ii. 各页组织成环形链表,指针指向最先调入的页面

算法

为每个页面设置一个访问位,再将内存中的页面都通过链接指针链接成一个循环队列。当某页被访问时,其访问位置为1。当需要淘汰一个页面时,只需检查页的访问位。如果是0,就选择该页换出;如果是1,则将它置为0,暂不换出,继续检查下一个页面,若第- - ~轮扫描中所有页面都是1,则将这些页面的访问位依次置为0后,再进行第二轮扫描(第二轮扫描中一定会有访问位为0的页面,因此简单的CLOCK算法选择–个淘汰页面最多会经过两轮扫描)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jgTcEqKZ-1592879546097)(https://camo.githubusercontent.com/be6880af7be4c35175b739114a78d6bf151c740f/68747470733a2f2f63732d6e6f7465732d313235363130393739362e636f732e61702d6775616e677a686f752e6d7971636c6f75642e636f6d2f35663565663062362d393865612d343937632d613030372d6636633535323838656162312e706e67)]

改进型的时钟置换操作

CLOCK算法的性能比较接近LRU,而通过增加使用的位数目,可以使得CLOCK算法更加高效。在使用位的基础上再增加一个修改位,则得到改进型的CLOCK置换算法。这样,每一帧都处于以下四种情况之一:

最近未被访问,也未被修改(u=0, m=0)。
最近被访问,但未被修改(u=1, m=0)。
最近未被访问,但被修改(u=0, m=1)。
最近被访问,被修改(u=1, m=1)。

算法执行如下操作步骤:

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

4.6最不常用算法(LFU,least frequently used)

实现:

i. 每个页面设置一个访问计数
ii. 访问页面时,访问计算加1
iii. 缺页时置换计算最小的页面

特征:

i. 算法开销大
ii. 开始频繁使用,但以后不使用的页面很难置换(计数后期右移)

LRU与LFU的区别:

i. LRU关注多久未访问,时间越短越好 维护一个栈
ii. LFU关注访问次数,次数越多越好

【操作系统】2.内存管理_第12张图片

Belady现象

Belady现象

当给一个进程增加页帧数分配时,在FIFO替换算法策略下可能会出现缺页率增加的异常现象。

【操作系统】2.内存管理_第13张图片

【操作系统】2.内存管理_第14张图片

以栈结构的算法无Belady

LRU、FIFO和Clock的比较

【操作系统】2.内存管理_第15张图片

【操作系统】2.内存管理_第16张图片

4.6 全局置换算法

思路:全局置换算法为进程分配可变数目的物理页面。

要解决的问题:

  1. 进程在不同阶段的内存需求是变化的
  2. 分配给进程的内存也需要在不同阶段有所变化
  3. 全局置换算法需要确定分配给进程的物理页面数

【操作系统】2.内存管理_第17张图片

工作集:一个进程当前正在使用的逻辑页面集合,可表示为二元函数W(t, delta)

  1. t是当前执行的时刻
  2. delta为当前工作集窗口,是一个定长的页面访问的时间窗口
  3. W(t, delta)是指当前时刻t前的delta时间窗口中的所有访问页面所组成的集合
  4. | W(t, delta) |指工作集大小,即页面数目

【操作系统】2.内存管理_第18张图片

常驻集:在当前时刻,进程实际驻留内存当中的页面集合。

a) 工作集与常驻集的关系:工作集是进程在运行过程中固有的性质。常驻集取决于系统分配给进程的物理页面数目和页面置换算法。

b) 缺页率与常驻集的关系:常驻集包含工作集时,缺页较少;工作集发生剧烈变动时,缺页较多;进程常驻集大小达到一定数目后,缺页率也不会明显下降。

4.7工作集置换算法

换出不在工作集中的页面

实现:

i. 维护一个窗口大小delta,表示当前时刻前delta个内存访问的页引用是工作集
ii. 访存链表:维护窗口内的访存页面链表
iii. 访存时,换出不在工作集的页面;更新访存链表
iv. 缺页时,换入页面;更新访存链表

4.8 缺页率置换算法:

a) 缺页率:缺页次数/内存访问次数 或 缺页平均时间间隔的倒数
b) 算法:通过调节常驻集大小,使每个进程的缺页率保持在一个合理的范围内。
c) 实现:访存时,设置引用位标志;缺页时计算从上次缺页时间Tlast到现在Tcurrent的时间间隔。

4.9抖动与负载控制:

a) 抖动

i. 进程物理页面太少,不能包含工作集合
ii. 造成大量缺页,频繁置换
iii. 进程运行速度变慢

b) 抖动的原因

随着进程驻留内存的进程数目增加,分配给每个进程的物理页面不断减少,缺页率不断上升。

操作系统需在并发水平和缺页率之间达到一个平衡:选择一个适当的进程数目和进程需要的物理页面数。

c) 负载控制:通过调节并发进程数MPL来进行系统负载控制

你可能感兴趣的:(操作系统)