清华大学《操作系统》(八):置换算法

功能:置换算法是指当出现缺页异常时,需要调入新页面而内存已满时,置换算法选择被置换的物理页面。

设计目标:

  • 尽可能减少页面的调入调出次数;
  • 把未来不再访问或短期内不访问的页面调出。

页面锁定:

了解具体的置换算法之前,先了解一个概念,页面锁定。页面锁定是用来描述某些必须常驻内存的逻辑页面,比如操作系统的关键部分,再比如一些要求响应速度的代码和数据。页面锁定是通过页表中的锁定标志位实现的。

分类:

  1. 局部置换算法:置换页面的选择范围仅限于当前进程占用的物理页面内。具体又有一系列算法:最优算法、先进先出算法、最近最久未使用算法,最近最久未使用算法又衍生出两种近似算法:时钟算法、最不常用算法,
  2. 全局置换算法:置换页面的选择范围是所有可换出的物理页面。具体有工作集算法、缺页率算法

最优界面置换算法: 

  • 基本思路:选择内存中等待时间最长(未来最长时间不访问)的页作为置换页面。 
  • 算法实现:缺页时,计算内存中每个逻辑页面的下一次访问时间;选择未来最长时间不访问的页面。
  • 算法特征:
  1. 只能是理想情况,OS无法实现(不知道未来情况)。 
  2. 可以作为最佳的标准,在第二遍运行时利用第一次的访问轨迹使用最优算法。其他算法应尽量逼近。

先进先出算法( first-in first-out FIFO)

  • 思路:选择在内存中驻留时间最长的页面并淘汰之。OS维护着一个队列链表,淘汰首位,添加末位。
  • 实现:维护一个记录所有位于内存中的逻辑页面;链表元素按驻留内存时间排序,链首最长,链尾最短;出现缺页时,选择链首页面进行置环,新页面加到链尾。
  • 特征:性能较差,调出的页面可能是常用页面(驻留时间长,本身就说明可能常用),有belady现象(给的物理页帧越多反而缺页越频繁)。因此该算法很少单独使用。

最近最久未使用算法(least recently used LRU)

  • 思路:选择最长时间没有被引用的页面进行置换。是对最优置换算法的近似,以过去推未来。根据程序的局部性原理,如果最近一段时间内某些页面被频繁访问,那么在将来还可能被频繁访问。反之,未被访问的将来也不会被访问。 程序应具有较好的局部性。
  • 实现:缺页时,计算内存中每个逻辑页面上一次访问时间;选择上一次使用到当前时间最长的页面
  • 特征:最优置换算法的一种近似,但仍然很复杂,很难实现。下面是LRU算法的两种可能的实现算法:
  1. 页面链表:系统维护一个按最近一次访问时间排序的页面链表,链表首节点是最近使用的页面,尾节点是最久未使用的页面,访问内存时找到相应页面,并把它移到链表之首,缺页时,置换链表尾节点的页面。
  2. 活动页面堆栈:访问页面时将此页号压入栈顶,并将栈内相同的页号抽出,缺页时置换栈底的页面。(栈是先进后出,只有栈顶开口,怎么push栈底?)
  3. 可以看到这两种方式存在一个问题就是平时不缺页时开销较大,每次访问页面都需要遍历链表或栈,找到相同的元素进行处理。

时钟置换算法(Clock):

时钟置换算法是最近最久未使用算法的优化。先进先出是完全不考虑最近访问情况,最近最久未使用算法是将所有页面在整个运行过程中的访问情况都进行考虑。而时钟置换算法是这两者的折中,即仅对页面的访问情况进行大致统计。具体实现

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

 

时钟置换算法实际还有一些改进。比如减少修改页的缺页处理开销。因为被修改的页如果要被置换,需要先写到外存,再将需要的页写入内存,开销至少乘2。因此为了减小修改过的页被置换,可以遇到被修改过的页指针就跳过。而在系统空闲时定期地将内存写入外存。实现通过在页面中增加修改位,并在访问时进行相应修改,缺页扫描时跳过有修改的页面。

改进的Clock算法

  • 思路:减少修改页得缺页处理开销
  • 算法:在页面增加修改位,并在访问时进行相应修改;缺页时,修改页面标志位,以跳过有修改得页面

最不常用置换算法(Least Frequently Used, LFU):

  • 思路:选择置换访问次数最少的那个页面 
  • 实现:对每个页面设置访问计数器,当一个页面被访问时加1。置换数值最小的那个。 
  • 特征:存在的问题就是统计开销大,并且新拿进来的页面可能因为计数较少马上又被置换出去,对于后面这个问题的一个解决方法是已经计的数定期地衰减
  • 最不常用置换算法页式最近最久未使用算法的优化。可以看到LFU与LRU的区别。LRU关注多久未被访问,时间越短越好,LFU关注访问次数,次数越多越好。

LFU与时钟算法都是对LRU算法的一种简化近似,开销减小,同时精度下降。LFU是比较难实现的,因此在内存管理中基本不会采用,但是在读硬盘文件的时候对时间要求不高的场景中还是可以使用的。

Belady现象

当一个进程频繁出现缺页异常时,应该分配给进程更多的物理页面,分配完后按照常理,缺页异常出现的频率应该降低。但是如果算法不好,很可能不会降低,我们把这种现象称为Belady现象。

比如FIFO算法,因为置换出去的页面不一定是进程近期不会访问的页面,如下图:

但是LRU算法是没有Belady现象的。时钟算法和改进的时钟算法也都是没有Belady现象的。分配更多的页面以为这更大的缓存,缓存越大命中率肯定升高。

综合比较局部页替换算法

LRU和FIFO的比较:LRU和FIFO本质都是先进先出,但LRU是页面的最近访问时间而不是进入内存的时间,有动态调整,符合栈算法的特性,空间越大缺页越少。如果程序局部性,则LRU会很好。如果内存中所有页面都没有被访问过会退化为FIFO。

Clock 和enhanced clock也是类似于FIFO的算法,但用了硬件的BIT来模拟了访问时间和顺序,近似了LRU,综合起来较好,但也会退化为FIFO。

都对程序的访问次序有局部性的要求,不然都会退化。

LRU、FIFO和Clock的比较:开销上,LRU开销大,FIFO开销小但BELADY,折中的是Clock算法,开销较小。对内存中还未被访问的页面,Clock效果等同LRU。Clock对曾经被访问过的则不能记住其准确位置,而LRU算法可以。

全局置换算法:

局部置换算法没有考虑进程访问的差异,有时候给一个进程多分配一个物理页面可以大幅度降低它的缺页率。全局置换算法就是要为进程分配可变数目的物理页面。它需要解决以下几个问题:

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

首先我们需要知道CPU利用率与并发进程数之间的关系。随着并发进程数从0增加,CPU的利用率也不断增大;当进程数越来越多,内存访问的局部性特征越来越被破坏,内存变的越来越紧张,利用率增长速度开始放缓,当增加到某个临界点,CPU利用率开始下降。也就是CPU利用率与并发进程数存在相互促进和制约的关系。

工作集

一个进程当前使用的逻辑页面集合,可以用一个二元函数W(t,Δ),t是当前执行时刻,Δ是工作集窗口(working-set window),一个定长的页面访问的时间窗口。t+Δ构成了一个时间段,W(t,Δ)就是在当前时刻t之前的Δ时间内所有访问页面组成的集合,在随t不断更新。| W(t,Δ)|是工作集的大小即页面数目。

工作集的变化:进程开始后,随着访问新页面逐步建立较稳定的工作集,当内存访问的局部性区域的位置大致稳定时| W(t,Δ)|波动很小,在过渡阶段,则会快速扩张和收缩过渡到下一个稳定值。有波峰,有波谷。


常驻集

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

工作集与常驻集的关系:工作集是固有性质,常驻集取决于系统分配给进程的物理页面数目和所采用的置换算法。

缺页率与常驻集的关系:当常驻集包含了工作集,也就是工作集都在内存中,缺页较少;工作集发生剧烈变动时,缺页较多;当常驻集大小达到某个数目后,再分配物理页帧也不会有明显下降的缺页率——可以把多出来的物理页帧分给其他程序了

工作集置换算法:

  • 思路:换出不在工作集中的页面
  • 窗口大小:当前时刻前τ个内存访问的页引用是工作集,τ被称为窗口大小
  • 实现方法:访存链表:维护窗口内的访存页面链表;在访存时,换出不在工作集的页面;缺页时,换入页面,更新访存链表。

工作集置换算法的思路是换出不在工作集中的页面。局部置换算法是在缺页异常发生时才决定置换哪个页面,但是工作集置换算法不一定是在缺页时才做这件事,而是在访存时就进行处理。工作集置换算法中有一个窗口大小 τ,当前时刻前 τ 个内存访问的页引用是工作集。

可以看到,缺页处理很简单,但是每次访存都要进行判断,开销还是很大的。这与LRU算法是类似的。

缺页率置换算法(Page-Fault-Frequency, PFF)

缺页率=缺页次数/内存访问次数 =1/缺页的平均时间间隔

影响因素有:页面置换算法,分配给进程的物理页面数目(越多越小),页面本身的大小(页面大则会小),编程方法(局部性好就会小)

缺页率置换算法是依据缺页率来决定哪些页面放到内存哪些被置换出去。其中我们能够控制的是页面置换算法。

正常情况下,随着分配给进程的物理页面数增多,缺页率会下降,缺页率置换算法通过调节常驻集的大小,使每个进程的缺页率保持在一个合理的范围内。如果缺页率过高,则增加物理页面数,如果缺页率过低,则降低物理页面数。

  • 思路:动态调整常驻集的大小。性能较好,但增加了系统开销 
  • 具体机制:
  1. 访存时设置引用位标志
  2. 缺页时,计算从上次缺页时间 tlast 到现在的时间 tcurrent 间隔,如果时间间隔 tcurrent - tlast 大于常量 T,则置换所有在 [tlast ,  tcurrent]  时间内没有被引用的页,以减少常驻集的大小;如果时间间隔 tcurrent - tlast 小于等于常量 T,则增加缺失页到常驻集。

对比缺页率置换算法与工作集置换算法,缺页率置换算法是在缺页异常时进行处理,工作集置换算法是在访存时进行处理,缺页的出现频率是远小于访存的,开销降下来了。

抖动

  • 抖动:如果分配给一个进程的物理页面太少,常驻集远小于工作集,则缺页率会很大,频繁在内外存之间替换页面,使进程的运行慢,这种状态成为”抖动”。
  • 产生抖动的原因:随着驻留内存的进程数目增加,分配给每个进程的物理页面数不断减少,缺页率上升。因此OS要选择一个适当的进程数目和进程需要的帧数,在并发水平和缺页率中达到平衡。

负载控制

我们希望平均缺页间隔时间(MTBF)大于等于缺页异常处理时间(PFST)。因此如下图右侧虚线以左是CPU满负荷工作也满足平均缺页间隔时间大于等于缺页异常处理时间的区域。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/454152.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python email模块详解_python模块之email: 电子邮件编码解码 (一、解码邮件)

python自带的email模块是个很有意思的东西,它可以对邮件编码解码,用来处理邮件非常好用。处理邮件是一个很细致的工作,尤其是解码邮件,因为它的格式变化太多了,下面先看看一个邮件的源文件:Received: from …

烂泥:通过vsphere给esxi添加本地硬盘

公司ESXi服务器的硬盘空间不够使用,现在新加了一块硬盘在ESxi服务器上。在服务器上添加完硬盘后,在Vsphere上是看不到新加硬盘的。 下面我们来通过虚拟机模拟该情况,先添加一块硬盘。如下图: 在Esxi添加完硬盘后,现在通…

清华大学《操作系统》(九):进程和线程

进程 定义: 进程是指一个具有一定独立功能的程序在一个数据集合上的一次动态执行的过程。 组成: 代码数据状态寄存器(正在运行的一个程序的所有状态信息):CPU状态CP0、指令指针IP通用寄存器:AX、BX、CX…

开始Flask项目

1.新建Flask项目。2.设置调试模式。3.理解Flask项目主程序。4.使用装饰器,设置路径与函数之间的关系。5.使用Flask中render_template,用不同的路径,返回首页、登录员、注册页。6.用视图函数反转得到URL,{{url_for(‘login’)}}&am…

gcc交叉编译的实现

gcc支持多种不同的语言,也支持多种不同的CPU架构。在它的实现上,不同语言编译的实现是通过conststruct lang_hooks lang_hooks LANG_HOOKS_INITIALIZER;这个结构体的不同定义来实现的。比如c语言的编译器就通过gcc/c-lang.c指定了lang_hooks这个结构体的…

烂泥:mysql数据库使用的基本命令

1、连接数据库的格式 mysql -h IP -u用户名 -p密码; 1.1连接远程数据库 mysql -h 192.168.1.214 -uroot -p123456 也可写成: mysql -h 192.168.1.214 -u root -p 123456 1.2连接本地数据库 mysql -uroot -p123456 也可写成: mysql -u root -p 123456 2、…

mse均方误差计算公式_PCA的两种解读:方差最大与均方误差最小的推导

这张图片很关键,来自统计学习方法的PCA插图又要考试了,推导一下方差最大化与均方差最小化,老师上课讲了一些均方差最小化,推导的过程很详细不过自己没有记下来,复习的时候再推一遍加深印象。感谢 耳东陈 老师的精彩课件…

《操作系统》OS学习(十):进程控制

进程切换(上下文切换): 定义:暂停当前运行进程,从运行状态变成其他状态,调度另一个进程从就绪状态变成运行状态要求:切换前,保存进程上下文;切换后,恢复进程…

日志管理

1、错误日志配置 错误日志属于核心功能模块的参数 worker_processes 1; error_log /data/logs/nginx/error.log error; #一般配置这一行即可 events {worker_connections 1024; }语法规则:error_log file level 错误的日志级别有[debug|info|notice|warn|err…

GCC 命令选项使用详解

GCC 命令行详解[转帖] 1、gcc包含的c/c编译器 gcc、cc、c、g gcc和cc是一样的,c和g是一样的,一般c程序就用gcc编译,c程序就用g编译 2、gcc的基本用法 gcc test.c这样将编译出一个名为a.out的程序 gcc test.c -o test这样将编译出一个名为t…

mvn 打包_Spark源码打包编译的过程

前言上篇文章介绍了下 安装sbt环境 启动scala项目安装SBT环境运行Scala项目为什么要弄这个 因为我本来是想对spark源码编译部署spark是用scala语言编译的spark源码https://gitee.com/pingfanrenbiji/sparkspark提供的编译方式编译的前提是将所有的依赖包都下载下来而资源包管理…

审计日志功能监控

背景:公司的审计日志经常出现不记录命令的情况,但是又无法监控到审计功能是否正常。所以我们思路是,每天从CMDB服务器 ssh登录到每一台主机。如果审计功能正常,则一定会在auditlog.info文件中有登录的记录。如果24小时内这个文件没…

清华大学《操作系统》(十一):处理机调度

一、处理机调度概念 进程切换(上下文切换):切换CPU的当前任务,从一个进程/线程到另一个,保存当前在PCB/TCB中的执行上下文,读取下一个的上下文 CPU调度:从就绪队列中挑选一个进程/线程作为CPU…

通过纯css实现图片居中的多种实现方式

html结构&#xff1a; 1 <div class"demo" style"width: 800px;height: 600px; border:1px solid #ddd"> 2 <img src"default.jpg" width"400" height"300"/> 3 </div> 实现img位于外层div的居中显示…

GCC 命令行详解

作者&#xff1a; www.linuxfans.org mozilla 1。gcc包含的c/c编译器 gcc,cc,c,g,gcc和cc是一样的&#xff0c;c和g是一样的&#xff0c;(没有看太明白前面这半句是什 么意思:))一般c程序就用gcc编译&#xff0c;c程序就用g编译 2。gcc的基本用法 gcc test.c这样将编译出一个…

Java网络编程从入门到精通(5):使用InetAddress类的getHostName方法获得域名

该方法可以得到远程主机的域名&#xff0c;也可以得到本机名。getHostName方法的定义如下&#xff1a; publicString getHostName() 下面是三种创建InetAddress对象的方式&#xff0c;在这三种方式中&#xff0c;getHostName返回的值是不同的。 1&#xff0e;使用getLocalHost方…

猿辅导python面试_猿辅导面试经历—个人感受

今天参加了猿辅导的二面&#xff0c;无数槽点&#xff0c;不知道是不是很多公司都是这样&#xff0c;但是我还是忍不住要逼逼叨。6月10号&#xff0c;我向猿辅导投了简历&#xff0c;想做招聘邀约专员这个岗位&#xff0c;然后hr加了我的微信&#xff0c;要了一份简历之后通知我…

对称加密与非对称加密

&#xff08;一&#xff09;对称加密&#xff08;Symmetric Cryptography&#xff09; 对称加密是最快速、最简单的一种加密方式&#xff0c;加密&#xff08;encryption&#xff09;与解密&#xff08;decryption&#xff09;用的是同样的密钥&#xff08;secret key&#xff…

清华大学《操作系统》(十二):临界区与锁

多进程并发运行&#xff0c;导致多个进程间有资源共享&#xff0c;比如CPU、内存&#xff0c;因此存在不确定性和不可重现&#xff0c;可能导致多次运行结果不一致。因此操作系统需要利用同步机制在并发执行的同时&#xff0c;保证一些操作是原子操作。 互斥是指一个进程占用了…

gcc生成静态库和动态库

gcc生成静态库和动态库一、库文件简介简单地说&#xff0c;库&#xff08;Library&#xff09;就是一组已经写好了的函数和变量、经过编译代码&#xff0c;是为了能够提高开发效率和运行效率而设计的。库分为静态库&#xff08;Static Library&#xff09;和共享库&#xff08;…