操作系统|| 虚拟内存页置换算法
题目
写一个程序来实现 FIFO 和 LRU 页置换算法。首先,产生一个随机的页面引用序列,页面数从 0~9。将这个序列应用到每个算法并记录发生的页错误的次数。实现这个算法时要将页帧的数量设为可变。假设使用请求调页。可以参考所示的抽象类。
抽象类:
public abstract class ReplacementAlgorithm
{
protected int pageFaultCount; // the number of page faults
protected int pageFrameCount; // the number of physical page frame
// pageFrameCount the number of physical page frames
public ReplacementAlgorithm(int pageFrameCount) {
if (pageFrameCount <0)
throw new IllegalArgumentException();
this.pageFrameCount = pageFrameCount;
pageFaultCount= 0; }
// return - the number of page faults that occurred
public int getPageFaultCount() {
return pageFaultCount;
}
// int pageNumber - the page number to be inserted
public abstract void insert (int pageNumber);
}
采用 LRU 页置换算法,另一个采用 FIFO 算法。
有两个类可以在线测试你的算法。
(1)PageGenerator——该类生成页面引用序列,页面数从 0~9。引用序列
的大小可作为 PageGenerateor 构造函数的参数。在创建 PageGenerator 对象后,
可用方法 getReferenceString0 方法返回作为引用序列的整数数组。
(2)Test-用来测试你的基于 ReplacementAlgorithm 的两个类 FIFO 与 LRU。
Test 可按如下方法调用:
Java Test <reference string #> <# of page frames>
算法介绍
先进先出算法(FIFO):缺页中断发生时,系统选择在内存中驻留时间最长的页面淘汰。通常采用链表记录进入物理内存中的逻辑页面,链首时间最长。
该算法实现简单,但性能较差,调出的页面可能是经常访问的页面,而且进程分配物理页面数增加时,缺页并不一定减少(Belady 现象)。
优点 :实现简单,只需要维护一个先进先出队列,每次淘汰时直接操作队列头部即可。
缺点 :性能较差,因为被调出的页面可能是经常访问的页面。会发生 Belady 现象(颠簸现象),当进程分配的物理页面数增加时,缺页次数反而可能增加。
Java伪代码:
public class FIFO {private Queue<Integer> queue = new LinkedList<>();private Set<Integer> pageSet = new HashSet<>();private int capacity;public FIFO(int capacity) {this.capacity = capacity;}public void accessPage(int page) {if (pageSet.contains(page)) {// 页面已在内存中,不需要处理return;}if (pageSet.size() < capacity) {// 内存未满,将页面加入队列和集合queue.offer(page);pageSet.add(page);System.out.println("页面 " + page + " 调入内存");} else {// 内存已满,淘汰队首页面int evictPage = queue.poll();pageSet.remove(evictPage);System.out.println("页面 " + evictPage + " 被淘汰");// 将新页面加入队列和集合queue.offer(page);pageSet.add(page);System.out.println("页面 " + page + " 调入内存");}}public static void main(String[] args) {FIFO fifo = new FIFO(3);int[] pages = {1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5};for (int page : pages) {System.out.print("访问页面 " + page + ":");fifo.accessPage(page);System.out.println("当前内存中的页面:" + fifo.pageSet);System.out.println();}}
}
最近最久未使用算法(LRU):算法思想是缺页发生时,选择最长时间没有被引用的页面进行置换,如某些页面长时间未被访问,则它们在将来还可能会长时间不会访问。该算法的开销较大。
优点 :具有较好的性能,能够较好地预测页面的使用频率。
缺点 :实现相对复杂,需要记录每个页面的访问时间,并且每次访问都需要更新访问时间。
Java伪代码:
public class LRU {private Map<Integer, Integer> pageMap = new HashMap<>();private List<Integer> pageList = new ArrayList<>();private int capacity;public LRU(int capacity) {this.capacity = capacity;}public void accessPage(int page) {if (pageMap.containsKey(page)) {// 页面已在内存中,更新其位置pageList.remove(Integer.valueOf(page));pageList.add(page);System.out.println("页面 " + page + " 已在内存中,更新其位置");} else {if (pageList.size() < capacity) {// 内存未满,将页面加入列表和映射pageList.add(page);pageMap.put(page, pageList.size() - 1);System.out.println("页面 " + page + " 调入内存");} else {// 内存已满,淘汰最久未使用的页面(列表开头的页面)int evictPage = pageList.remove(0);pageMap.remove(evictPage);System.out.println("页面 " + evictPage + " 被淘汰");// 将新页面加入列表和映射pageList.add(page);pageMap.put(page, pageList.size() - 1);System.out.println("页面 " + page + " 调入内存");}}}public static void main(String[] args) {LRU lru = new LRU(3);int[] pages = {1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5};for (int page : pages) {System.out.print("访问页面 " + page + ":");lru.accessPage(page);System.out.println("当前内存中的页面:" + lru.pageList);System.out.println();}}
}
关键步骤
(1)在PageGenerator类中,构造函数PageGenerator(int count)中生成随机的页面引用序列。
public PageGenerator(int count) {if (count < 0)throw new IllegalArgumentException();java.util.Random generator = new java.util.Random();referenceString = new int[count];for (int i = 0; i < count; i++)referenceString[i] = generator.nextInt(RANGE + 1);
}
(2)在ReplacementAlgorithm抽象类的子类FIFO和LRU中,实现页面置换算法。
FIFO类:实现FIFO算法(First-In, First-Out):将最早插入的页面替换出去。
@Override
public void insert(int pageNumber) {boolean pageFault = true;// 检查页面是否已经在物理页面帧中for (int i = 0; i < pageFrameCount; i++) {if (pageFrames[i] == pageNumber) {pageFault = false;break;}}// 如果页面不在物理页面帧中,则发生页面错误if (pageFault) {pageFaultCount++;pageFrames[currentIndex] = pageNumber;currentIndex = (currentIndex + 1) % pageFrameCount;}
}
LRU类:实现LRU算法(Least Recently Used):将最长时间未被使用的页面替换出去
@Override
public void insert(int pageNumber) {boolean pageFault = true;int oldestTimestampIndex = 0;int oldestTimestamp = timestamps[0];// 检查页面是否已经在物理页面帧中for (int i = 0; i < pageFrameCount; i++) {if (pageFrames[i] == pageNumber) {pageFault = false;// 更新页面的时间戳timestamps[i] = getCurrentTimestamp();break;}// 找到最老的时间戳和对应的页面帧索引if (timestamps[i] < oldestTimestamp) {oldestTimestamp = timestamps[i];oldestTimestampIndex = i;}}// 如果页面不在物理页面帧中,则发生页面错误if (pageFault) {pageFaultCount++;pageFrames[oldestTimestampIndex] = pageNumber;timestamps[oldestTimestampIndex] = getCurrentTimestamp();}
}
(3)在Test类中,使用FIFO和LRU算法计算页面错误次数。
PageGenerator ref = new PageGenerator(new Integer(args[0]).intValue());int[] referenceString = ref.getReferenceString();/** Use either the FIFO or LRU algorithms */
ReplacementAlgorithm fifo = new FIFO(new Integer(args[1]).intValue());
ReplacementAlgorithm lru = new LRU(new Integer(args[1]).intValue());// 插入页面时输出消息
for (int i = 0; i < referenceString.length; i++) {// System.out.println("inserting " + referenceString[i]);lru.insert(referenceString[i]);
}// 插入页面时输出消息
for (int i = 0; i < referenceString.length; i++) {// System.out.println("inserting " + referenceString[i]);fifo.insert(referenceString[i]);
}// 报告页面错误总数
System.out.println("LRU faults = " + lru.getPageFaultCount());
System.out.println("FIFO faults = " + fifo.getPageFaultCount());
源码
/*** This class generates page references ranging from 0 .. 9** Usage:* PageGenerator gen = new PageGenerator()* int[] ref = gen.getReferenceString();*/public class PageGenerator
{private static final int DEFAULT_SIZE = 100;private static final int RANGE = 9;int[] referenceString;public PageGenerator() {this(DEFAULT_SIZE);}public PageGenerator(int count) {if (count < 0)throw new IllegalArgumentException();java.util.Random generator = new java.util.Random();referenceString = new int[count];for (int i = 0; i < count; i++)referenceString[i] = generator.nextInt(RANGE + 1);}public int[] getReferenceString() {/*** comment out the following two lines to* generate random reference strings*/int[] str = {7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1};//int[] str = {1,2,3,4,1,2,5,1,2,3,4,5};return str;/*** and uncomment the following line*/ //return referenceString;}
}
/*** ReplacementAlgorithm.java **/public abstract class ReplacementAlgorithm
{// the number of page faultsprotected int pageFaultCount;// the number of physical page frameprotected int pageFrameCount;/*** @param pageFrameCount - the number of physical page frames*/public ReplacementAlgorithm(int pageFrameCount) {if (pageFrameCount < 0)throw new IllegalArgumentException();this.pageFrameCount = pageFrameCount;pageFaultCount = 0;}/*** @return - the number of page faults that occurred.*/public int getPageFaultCount() {return pageFaultCount;}/*** @param pageNumber - the page number to be inserted*/public abstract void insert(int pageNumber);
}
public class FIFO extends ReplacementAlgorithm{private int[] pageFrames;private int currentIndex;public FIFO(int pageFrameCount){super(pageFrameCount);pageFrames = new int[pageFrameCount];currentIndex = 0;}@Overridepublic void insert(int pageNumber) {boolean pageFault = true;//check pages whether in pageFramesfor(int i =0;i<pageFrameCount;i++){if(pageFrames[i]==pageNumber){pageFault = false;break;}}//if pages not in pagesFrames,it happens faultsif(pageFault){pageFaultCount++;pageFrames[currentIndex] = pageNumber;currentIndex = (currentIndex+1)%pageFrameCount;}}
}
public class LRU extends ReplacementAlgorithm{private int[] pageFrames;private int[] timestamps;/*** @param pageFrameCount - the number of physical page frames*/public LRU(int pageFrameCount) {super(pageFrameCount);pageFrames = new int[pageFrameCount];timestamps = new int[pageFrameCount];}@Overridepublic void insert(int pageNumber) {boolean pageFault = true;int oldestTimestampIndex = 0;int oldestTimestamp = timestamps[0];//check pages whether in pagesFramesfor(int i =0;i<pageFrameCount;i++){if(pageFrames[i]==pageNumber){pageFault = false;//upgrade pageTimestapstimestamps[i] = getPageFaultCount();break;}if(timestamps[i]<oldestTimestamp){oldestTimestamp = timestamps[i];oldestTimestampIndex = i;}}//if not in pagesFrame,happen faultsif(pageFault){pageFaultCount++;pageFrames[oldestTimestampIndex]=pageNumber;timestamps[oldestTimestampIndex]=getCurrentTimestamp();}}//acquire current timestampprivate int getCurrentTimestamp(){return pageFaultCount+1;}
}
/*** Test harness for LRU and FIFO page replacement algorithms**/public class Test
{public static void main(String[] args) {if (args.length != 2) {System.err.println("Usage: java Test <reference string size> <number of page frames>");System.exit(-1);}PageGenerator ref = new PageGenerator(Integer.valueOf(args[0]).intValue());int[] referenceString = ref.getReferenceString();/** Use either the FIFO or LRU algorithms */ReplacementAlgorithm fifo = new FIFO(Integer.valueOf(args[1]).intValue());ReplacementAlgorithm lru = new LRU(Integer.valueOf(args[1]).intValue());// output a message when inserting a pagefor (int i = 0; i < referenceString.length; i++) {//System.out.println("inserting " + referenceString[i]);lru.insert(referenceString[i]);}// output a message when inserting a pagefor (int i = 0; i < referenceString.length; i++) {//System.out.println("inserting " + referenceString[i]);fifo.insert(referenceString[i]);}// report the total number of page faultsSystem.out.println("LRU faults = " + lru.getPageFaultCount());System.out.println("FIFO faults = " + fifo.getPageFaultCount());}
}
运行结果
参数设置 20-3
参数设置 20-4
思考
在实现了 FIFO 与 LRU 算法后,给定引用序列,试验不同页帧的数量所产
生的缺页次数。并分析:一个算法比另一好么?对给定引用序列,页帧的最佳数
量是多少?假设给定引用序列 1,2,3,4,1,2,5,1,2,3,4,5,当页帧
数分别为 3 和 4 时,用 FIFO 置换算法时缺页中断分别为多少?
根据代码,可以通过修改 Test 类的 main 方法中的 args 数组来改变页面帧的数量和引用序列的大小。以下是分别使用 FIFO 和 LRU 置换算法对给定引用序列进行测试的结果:
(1)当页帧数为 3 时:
使用 FIFO 置换算法,缺页次数为 9
使用 LRU 置换算法,缺页次数为 9
相关文章:

操作系统|| 虚拟内存页置换算法
题目 写一个程序来实现 FIFO 和 LRU 页置换算法。首先,产生一个随机的页面引用序列,页面数从 0~9。将这个序列应用到每个算法并记录发生的页错误的次数。实现这个算法时要将页帧的数量设为可变。假设使用请求调页。可以参考所示的抽象类。 抽象类&…...

Maven 项目构建时编译错误问题排查与解决
1. 问题描述 Maven 项目执行命令 mvn clean package 时出现编译错误,如下图所示 2. 问题分析 由于是源码编译错误,于是通过查看项目 pom.xml 文件,得到项目源码使用的 Java 版本为 21 <project xmlns"http://maven.apache.org/P…...
5 Celery多节点部署
一、多节点部署架构设计 1.1 典型生产环境拓扑 #mermaid-svg-NjPQBLvUUsBc24uk {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-NjPQBLvUUsBc24uk .error-icon{fill:#552222;}#mermaid-svg-NjPQBLvUUsBc24uk .error…...
FPGA:Lattice的FPGA产品线以及器件选型建议
本文将详细介绍Lattice Semiconductor的FPGA产品线,帮助你了解各系列的特点和适用场景,以便更好地进行选型。Lattice以低功耗、小尺寸和高性能为核心,产品覆盖低中端市场,广泛应用于通信、计算、工业、汽车、消费电子、嵌入式视觉…...

安全生产调度管理系统的核心功能模块
安全生产调度管理系统是运用现代信息技术构建的智能化管理平台,旨在实现生产安全风险的全面管控和应急资源的优化调度。该系统通过整合物联网、大数据、人工智能等前沿技术,建立起覆盖风险监测、预警预测、指挥调度、决策支持的全链条安全管理体系。 一…...
R语言学习--Day03--数据清洗技巧
在一般情况下,我们都是在数据分析的需求前提下去选择使用R语言。而实际上,数据分析里,百分之八十的工作,都是在数据清洗。并不只是我们平时会提到的异常值处理或者是整合格式,更多会涉及到将各种各样的数据整合&#x…...

Linux进程信号(一)之信号的入门
文章目录 信号入门1. 生活角度的信号2. 技术应用角度的信号3. 注意4. 信号概念5.用kill -l命令可以察看系统定义的信号列表6. 信号处理常见方式 信号入门 1. 生活角度的信号 你在网上买了很多件商品,再等待不同商品快递的到来。但即便快递没有到来,你也…...

基于springboot+vue的机场乘客服务系统
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7数据库工具:Navicat12开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9 系统展示 用户管理 航班信…...

基于SpringBoot的房屋租赁管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...
redis数据结构-11(了解 Redis 持久性选项:RDB 和 AOF)
了解 Redis 持久性选项:RDB 和 AOF Redis 提供了多个持久性选项,以确保数据持久性并防止在服务器发生故障或重启时丢失数据。了解这些选项对于为您的特定使用案例选择正确的策略、平衡性能和数据安全至关重要。本章节将深入探讨 Redis 中的两种主要持久…...

STM32外设AD/DA-基础及CubeMX配置
STM32外设AD/DA-基础及CubeMX配置 一,什么是AD/DA二,基础概念1,模拟 vs 数字2,AD转换1,分辨率 (Resolution)2,参考电压 (Reference Voltage, Vref)3,采样率 (Sampling Rate) 3,DA转换…...

React Native简介
React Native 是由 Meta(原 Facebook)开源的跨平台移动应用开发框架,基于 React 和 JavaScript,允许开发者使用同一套代码库构建 iOS 和 Android 原生应用。通过 JavaScript 调用原生组件实现高性能渲染。 跨平台开发 共享 80%-9…...
微服务如何实现服务的高并发
高并发的常见指标 响应时间吞吐量每秒查询率QPS并发用户数 高并发是分布式系统架构设计必须的考虑因素 具体实现方案粗略分两种: 垂直扩展 硬件升级方向 处理器:增加CPU核数(如升级至32核以上)或采用更高主频的CPU存储设备…...

GCC 使用说明
参数 -fPIC ppc_85xx-gcc -shared -fPIC liberr.c -o liberr.so -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code), 则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加…...
码蹄集——圆包含
MT1181 圆包含 输入2个圆的圆心的坐标值(x,y)和半径,判断断一个圆是否完全包含另一个圆,输出YES或者NO。另:内切不算做完全包含。 格式 输入格式:输入整型,空格分隔。 每行输入一组…...
CSR、SSR与ISR的奇妙之旅
网页渲染三剑客:CSR、SSR与ISR的奇妙之旅 三种渲染方式的核心本质 CSR(客户端渲染)让浏览器成为"厨师",SSR(服务器端渲染)让服务器担任"厨师",而ISR(增量静态再生)则是一位兼具"提前备餐"和"即时烹饪"能力的"超级厨师"…...

Verilog HDL 语言整理
Verilog HDL 语言 Verilog HDL 简介 硬件描述语言Hardware Description Language是一种用形式化方法即文本形式 来描述和设计数字电路和数字系统的高级模块化语言 Verilog HDL(Hardware Description Language)是一种硬件描述语言,用于建模…...

车道线检测----Lane-ATT
本文针对车道线检测----Lane-ATT论文所有细节进行阐述,有帮助的话点个收藏关注吧 保持对车道的关注:注意力引导的车道检测 摘要 但许多方法在保持实时效率方面存在问题,这对于自动驾驶车辆至关重要。在本文中,我们提出了LaneATT…...

linux安装宝塔面板到数据盘
操作很简单,假如数据盘挂载在cipan1,在数据盘新建目录www,为了方便对应。 执行一下命令,创建软连接 ln -s /cipan1/www www 此时,根目录就出现了www文件夹 下面正常安装宝塔即可...

【基础】Windows开发设置入门7:PowerShell的相关概念和使用
前言 大家熟悉的docker、Python,但对于Windows上有一套开配合开发的相对底层的环境设置,包括powershell、winget、WSL、还有开发驱动器什么的,我准备系统学一下,不然地基不牢,也盖不起冲天高楼~ 本节,介绍…...
【python基础知识】Day 27 函数专题2:装饰器
知识点: 装饰器的思想:进一步复用函数的装饰器写法注意内部函数的返回值 装饰器教程 作业: 编写一个装饰器 logger,在函数执行前后打印日志信息(如函数名、参数、返回值) def logger(func):def wrapper(*ar…...

芯片生态链深度解析(一):基础材料篇——从砂砾到硅基王国的核心技术突围
【开篇:芯片——现代文明的“炼金术”】 当您滑动手机屏幕、驾驶新能源汽车、甚至用AI生成一幅画时,是否想过这些科技奇迹都始于一粒沙子?芯片,这个边长不足2厘米的黑色薄片,正是通过将砂砾提纯为高纯度硅锭ÿ…...

一款利用ADB (安卓调试桥)来控制手机的玩机工具
—————【下 载 地 址】——————— 【本章下载一】:https://drive.uc.cn/s/f36ed8ff62f74 【本章下载二】:https://pan.xunlei.com/s/VOQDmKCq4u-CygjX9Tcn3fxEA1?pwdwf3t# 【百款黑科技】:https://ucnygalh6wle.feishu.cn/wiki/…...

使用mermaid 语言绘画时序图和链路图
给大家展示一下效果, 官方地址:https://mermaid.nodejs.cn/ 官方开发地:https://mermaid.nodejs.cn/intro/#google_vignette graph LR%% 样式定义(完全保留) classDef user fill:#E1F5FE,stroke:#0288D1;classDef …...

浅论3DGS溅射模型在VR眼镜上的应用
摆烂仙君小课堂开课了,本期将介绍如何手搓VR眼镜,并将随手拍的电影变成3D视频。 一、3DGS模型介绍 3D 高斯模型是基于高斯函数构建的用于描述三维空间中数据分布概率的模型,高斯函数在数学和物理领域有着广泛应用,其在 3D 情境下…...

6种方式来探究数据集的的方法worldquant
覆盖率百分比 指金融数据字段(如股价、成交量、财务指标)在时间或空间上的有效数据比例。 时间维度:数据在历史周期内的完整度(如:某股票过去 1 年中,95% 的交易日有收盘价)。空间维度…...

深度学习中的归一化:提升模型性能的关键因素
📌 友情提示: 本文内容由银河易创AI(https://ai.eaigx.com)创作平台的gpt-4-turbo模型辅助完成,旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证,建议读者通过官方文档或实践进一步确认…...

vue+threeJS 大理石贴图
嗨,我是小路。今天主要和大家分享的主题是“vuethreeJS 大理石贴图”。 通过 Vue 3 和 Three.js 实现大理石纹理效果,并将这种技术应用于产品展示、虚拟展览、甚至是互动游戏之中,其潜力无穷。今天主要介绍基础的大理石贴图。 vueth…...

WebGL 3着色器和GLSL
我们之前提到过着色器和GLSL,但是没有涉及细节,你可能已经对此有所了解, 但以防万一,这里将详细讲解着色器和GLSL。 在工作原理中我们提到,WebGL每次绘制需要两个着色器, 一个顶点着色器和一个片段着色器&…...
vscode debug node + 前端
方法 2:调试全栈(Node 前端) 如果需同时调试后端和前端: 分别启动两个调试会话 一个配置调试 Node.js 后端(server.js)。 另一个配置调试浏览器前端(如上)。 {// Use IntelliS…...