1. 页面置换的概念
功能:选择被置换的物理页面
设计目标:
- 减少页面的调入调出的次数
 - 将未来或短期内不访问的页面调出
 
页面锁定:不可以置换的页面
即页表项中的标志锁定位置1的页面(通常是操作系统页面,需要高读写的页面等)
1.1 局部置换
选择范围:当前进程占用的物理页面
分为:
- 最优算法
 - 先进先出算法
 - 最近最久未使用算法
 
1.2 全局置换
选择范围:所有可换出的物理页面
分为:
- 工作集算法
 - 置换率算法
 
2. 三大局部置换解决算法
2.1 最优页面置换算法 optimal
思路: 未来时间不会访问的页面
实现:
- 缺页时,计算每个页面下一次访问的时间
 - 选择未来最长时间访问的页面
 
特征:
- 缺页最少
 - 实际上无法实现
 - 因为无法预知
 - 可以作为其他置换算法的性能评价依据
 

2.2 先进先出算法 FIFO
思路:在内存驻留时间最长的页面进行置换
实现:
- 维护一个记录所有位于内存中的逻辑页面链表
 - 按驻留内存的时间排序,链首最长,链尾最短
 - 缺页时,选择链首页面进行置换,新页面添加到链尾
 
特征:
- 实现简单
 - 性能较差,调出的页面可能经常访问
 - 进程分配物理页面数增加时,缺页不一定减少(Belady现象)
 - 很少单独使用
 

2.3 最近最久未使用算法 LRU (Least Recently Used)
思路:选择最长时间没有被引用的页面进行置换
(如某些页面长时间未被访问,在未来可能会长时间不会访问)
实现:
- 缺页时,计算每个页面上一次访问的时间
 - 选择上一次使用到当前时间最长的页面
 
特征:
- 最优置换算法的一种近似
 

2.4 LRU算法的可能实现办法
- 页面链表
- 按最近一次访问的时间排序的页面链表
 - 链表首节点是最近访问的页面
 - 尾节点是最久未使用的页面
 
 - 活动页面栈
- 访问页面时,将此页号压入栈顶,并在栈内相同的页号抽出
 - 缺页时,置换栈底的页面
 
 
特征:
    开销大
用栈实现LRU算法

3. 时钟置换算法和最不常用算法
3.1 时钟置换算法 clock (FIFO和LRU的折中版)
思路:仅对页面的访问情况进行大致统计
数据结构:
- 在页表项中增加访问位,描述页面在过去一段时间呃访问情况
 - 各页面组织成环形链表
 - 指针指向最先调入的页面
 
算法:
- 访问页面时,在页表项记录页面的访问情况(访问位置1)
 - 缺页时,从指针处开始顺序查找未被访问的页面进行置换
 
特征:
    LRU和FIFO的折中
替换前:

替换后:

示例:


改进的clock算法
思路:
    减少了修改页的缺页处理开销
算法:
    页表项增加修改位
    缺页时,修改页面标志位,跳过修改的页面

读 ——> 10
写 ——> 11
找置换时:
11 ——> 01
10/01 ——> 00
00 ——> 置换 (然后该页面为10)

3.2 最不常用算法 LFU (Least Frequently Used)
思路:
    缺页时,置换访问次数最少的页面
实现:
- 每个页面设置一个访问计数
 - 访问每个页面时,访问次数+1
 - 缺页时,置换计数最小的页面
 
特征:
- 开销大
 - 解决办法:衰减右移
 
LRU 和 LFU 的区别
- LRU 关注多久未访问,时间越短越好
 - LFU 关注访问次数,次数越多越好
 

4. Belady现象 和 局部置换算法的比较
4.1 Belady现象
现象:
    采用FIFO等算法时,可能出现分配的物理页面数增加,缺页次数反而升高的异常现象
原因:
1. FIFO算法的置换特征与进程访问内存的动态特征矛盾
2. 被它置换出去的页面并不一定是进程近期不会访问的
物理页数为 3

+1后,物理页数为 4

证明:存在 belady现象
LRU算法没有Belady现象!
4.2 LRU,FIFO和clock算法的比较
LRU 和 FIFO 本质上都是先进先出的思路
- LRU依据页面的最近访问时间排序
 - LRU需要动态调整顺序(维护一个栈…)
 - FIFO依据页面进入内存的时间排序
 - FIFO的页面进来后是固定不变的
 
LRU 可以退化成FIFO
如:1,2,3,4,5,6,1,2,3
比较
- LRU 性能好,开销大
 - FIFO 性能差,但会发生Belady现象
 - clock 是他们的折中
- 页面访问时,不动态调整页面在链表中的顺序,仅作标记
 - 缺页时,再把它移动到链表末尾
 
 
5. 全局页面置换算法
局部置换算法没有考虑进程访问的差异
思路:全局置换算法为进程分配可变数目的物理页面
问题?
- 进程再不同阶段的内存需求是变化的
 - 分配给进程的内存在需要不同阶段有所变化
 - 全局置换算法需要确定分配给进程的物理页面数
 
5.1 工作集置换算法
工作集:一个进程当前正在使用的逻辑页面集合,可表示为二元函数W(t, delta)

示例:

工作集的变化:

工作集置换算法
思路:换出不在工作集的页面
窗口大小 t :
   当前时刻前t个内存访问的页引用是工作集,t被称为窗口大小
实现方法:
- 访存链表:维护窗口内的访存页面链表
 - 访存时,换出不在工作集的页面,更新访存链表 (复杂的地方)
 - 缺页时,换入页面,更新访存链表
 
缺点:
    开销大

5.2 缺页率算法
缺页次数 / 内存访问次数 or 缺页平均时间间隔的倒数的平均值
影响的因素:
- 页面置换算法 (可控制的)
 - 分配给进程的物理页面数目
 - 页面大小
 - 程序的编写方法
 

缺页率置换算法 图示:

实现:
- 访存时,设置引用标志
 - 缺页时,计算从上次缺页时间T_last到现在T_current的时间间隔
- T_current - T_last > T 置换所有在[T_last, T_current]的页面
 - T_current - T_last < T 增加缺失页放入常驻集中
 
 

6. 抖动和负载控制
6.1 抖动问题
抖动:
- 进程中物理页面太少,不能包含工作集
 - 造成大量缺页,频繁置换
 - 进程运行速度变慢
 
产生抖动的原因:
- 驻留在内存的进程数目增加,分配给每个进程的物理页面减少,缺页率上升
 
需要在并发和缺页率之间达到一个平衡
6.2 负载控制
调节并发进程数 MPL 来进行系统负载控制
