操作系统之内存管理

1. 功能

内存管理实现的功能:

  • 抽象:逻辑地址空间
  • 保护:独立地址空间
  • 共享:访问相同内存
  • 虚拟化:更大的地址空间

2. 管理方式

2.1 重定位

使用基址寄存器和界限寄存器,程序的起始物理地址装载到基址寄存器中,程序的长度装载到界限寄存器中。寻址时,地址=基址+偏移。

2.2 分段

将内存分为堆、堆栈、数据段、代码段等。

2.3 分页

  • 页帧(帧、物理页面、Frame、Page Frame)
  • 页面(页、逻辑页面、Page)
  • 页表:页到帧的映射,逻辑地址中的页号是连续的,物理地址中的帧号是不连续的,不是所有的页都有对应的帧,每个进程都有一个页表,随进程运行状态而动态变化。

分页带来的问题:

  • 内存访问性能问题:访问一个内存单元需要两次内存访问。
  • 页表大小问题:页表可能非常大。

处理方法:

  • 快表:缓存
  • 多级页表
  • 反置页表(倒排页表):实际内存中每个页帧对应一个表项,用虚拟地址进行散列

2.4 段页式

段式存储在内存保护方面有优势,页式存储在内存利用和优化转移到后备存储方面有优势。段页式是在段式存储的管理基础上,给每个段加一级页表。

这种方式通过指向相同的页表基址,容易实现进程间的内存共享。
在这里插入图片描述

2.5 虚拟存储

2.5.1 基本特征

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

2.5.2 缺页异常(中断)的处理流程

  • A.在内存中有空闲的物理页面时,分配一物理页帧 f,转第 E 步
  • B.依据页面置换算法选择将被替换的物理页帧 f,对应逻辑页 q
  • C.如 q 被修改过,则把它写回外存
  • D.修改 q 的页表项中的驻留位为 0
  • E.将需要访问的页 p 装入到物理页面 f
  • F.修改 p 的页表驻留位为 1,物理帧号为 f
  • G.重新执行产生缺页的指令

2.5.3 页面置换算法

2.5.3.1 局部页面置换算法

置换页面的选择范围仅限于当前进程占用的物理页面内。

1. 最优算法(OPT,optimal)

思路:置换在未来最长时间不访问的页面。
实现:缺页时,计算内存中每个逻辑页面的下一次访问时间,选择未来最长时间不访问的页面。
特征

  • 缺页最少,是理想情况。
  • 实际系统中无法实现,无法预知每个页面在下次访问前的等待时间。
  • 可作为置换算法的性能评价依据。
2. 先进先出算法(First-In First-Out,FIFO)

思路:选择在内存中驻留时间最长的页面进行置换。
实现:维护一个记录所有位于内存中的逻辑页面链表,链表元素按驻留内存的时间排序,链首最长,链尾最短。出现缺页时,选择链首页面进行置换,新页面加到链尾。
特征

  • 实现简单
  • 性能较差,调出的页面可能是经常访问的
  • 进程分配物理页面数增加时,缺页并不一定减少(Belady 现象):采用 FIFO 等算法时,可能出现分配的物理页面数增加,缺页次数反而升高的异常现象。原因:FIFO 算法的置换特征与进程访问内存的动态特征矛盾,被它置换出去的页面并不一定是进程近期不会访问的。
  • 很少单独使用
3. 最近最少使用算法(Least Recently Used,LRU)

思路:缺页时,计算内存中每个逻辑页面的上一次访问时间,选择上一次使用到当前时间最长的页面。
实现:维护一个按最近访问时间排序的页面链表。
特征:开销比较大,每次访问要更新链表。

4. 时钟算法(Clock)

思路:仅对页面的访问情况进行大致统计。
数据结构:在页表项中增加访问位,描述页面在过去一段时间的内存访问情况,各页面组织成环形链表,指针指向最先调入的页面。
算法:访问页面时,在页表项记录页面访问情况,缺页时,从指针处开始顺序查找未被访问的页面进行置换。
实现:页面装入内存时,访问位初始化为 0,访问页面时,访问位置 1。缺页时,从指针当前位置顺序检查环形链表:访问位为 0,则置换该页;访问位为 1,则访问位置 0,并指针移动到下一个页面,直到找到可置换的页面。
特征
是 LRU 和 FIFO 的折中。

5. 改进的 CLock 算法

思路:减少修改页的缺页处理(写入外存)开销。
算法:在页表项增加修改位,并在访问时进行相应修改。缺页时,修改页面标志位,以跳过有修改的页面。

6. 最不常用算法(Least Frequently Used,LFU)

思路:缺页时,置换访问次数最少的页面。
实现:每个页面设置一个访问计数,访问页面时,访问计数加 1 ,缺页时,置换计数最小的页面。
特征

  • 开销大。
  • 开始时使用频繁,但以后不使用的页面很难置换。解决方法:计数定期右移。
LRU、FIFO 和 Clock 的比较
  • LRU 和 FIFO 本质上都是先进先出的思路:LRU 依据页面的最近访问时间排序;FIFO 依据页面进入内存的时间排序。
  • LRU 需要动态地调整顺序,FIFO 的页面进入时间是固定不变的。
  • LRU 可退化成 FIFO:如页面进入内存后没有被访问,最近访问时间与进入内存的时间相同。
  • LRU 算法性能较好,但系统开销大;FIFO 算法系统开销较小,但会发生 Belady 现象。
  • Clock 算法是它们的折中,页面访问时,不动态调整页面在链表中的顺序,仅做标记,缺页时,再把它移动到链表末尾。
  • 对于未被访问的页面,Clock 和 LRU 算法的表现一样好。对于被访问过的页面,Clock 算法不能记录准确访问顺序,而 LRU 算法可以。

2.5.3.2 全局页面置换算法

置换页面的选择范围是所有可换出的物理页面,为进程分配可变数目的物理页面。进程在不同阶段的内存需求是变化的,分配给进程的内存也需要在不同阶段有所变化。全局置换算法需要确定分配给进程的物理页面数。

CPU 利用率与并发进程数的关系:
在这里插入图片描述

  • 进程数少时,提高并发进程数,可提高 CPU 利用率。
  • 并发进程导致内存访问增加。
  • 并发进程的内存访问会降低访存的局部性特征。
  • 局部性特征的下降会导致缺页率上升和 CPU 利用率下降。

工作集:一个进程当前正在使用的逻辑页面集合,可表示为二元函数W(t,△),t 是当前的执行时刻,△ 称为工作集窗口,即一个定长的页面访问时间窗口。

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

1. 工作集算法

换出不在工作集中的页面。

2. 缺页率算法

缺页率=缺页次数 / 内存访问次数 或 缺页平均时间间隔的倒数。
通过调整常驻集大小,使每个进程的缺页率保持在一个合理的范围内。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章