操作系统|| 虚拟内存页置换算法

news2025/5/17 11:26:09

题目

写一个程序来实现 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 faults
	protected int pageFaultCount;
	
	// the number of physical page frame
	protected 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;

    }
    @Override
    public void insert(int pageNumber) {
        boolean pageFault = true;
        //check pages whether in pageFrames
        for(int i =0;i<pageFrameCount;i++){
            if(pageFrames[i]==pageNumber){
                pageFault = false;
                break;
            }
        }

        //if pages not in pagesFrames,it happens faults
        if(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];
    }

    @Override
    public void insert(int pageNumber) {
        boolean pageFault = true;
        int oldestTimestampIndex = 0;
        int oldestTimestamp = timestamps[0];
        //check pages whether in pagesFrames
        for(int i =0;i<pageFrameCount;i++){
            if(pageFrames[i]==pageNumber){
                pageFault = false;
                //upgrade pageTimestaps
                timestamps[i] = getPageFaultCount();
                break;
            }
            if(timestamps[i]<oldestTimestamp){
                oldestTimestamp = timestamps[i];
                oldestTimestampIndex = i;
            }
        }
        //if not in pagesFrame,happen faults
        if(pageFault){
            pageFaultCount++;
            pageFrames[oldestTimestampIndex]=pageNumber;
            timestamps[oldestTimestampIndex]=getCurrentTimestamp();

        }
    }
    //acquire current timestamp
    private  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 page
		for (int i = 0; i < referenceString.length; i++) {
			//System.out.println("inserting " + referenceString[i]);
			lru.insert(referenceString[i]);
		}

		// output a message when inserting a page
		for (int i = 0; i < referenceString.length; i++) {
			//System.out.println("inserting " + referenceString[i]);
			fifo.insert(referenceString[i]);
		}

		// report the total number of page faults
		System.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

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

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

相关文章

Maven 项目构建时编译错误问题排查与解决

1. 问题描述 Maven 项目执行命令 mvn clean package 时出现编译错误&#xff0c;如下图所示 2. 问题分析 由于是源码编译错误&#xff0c;于是通过查看项目 pom.xml 文件&#xff0c;得到项目源码使用的 Java 版本为 21 <project xmlns"http://maven.apache.org/P…

安全生产调度管理系统的核心功能模块

安全生产调度管理系统是运用现代信息技术构建的智能化管理平台&#xff0c;旨在实现生产安全风险的全面管控和应急资源的优化调度。该系统通过整合物联网、大数据、人工智能等前沿技术&#xff0c;建立起覆盖风险监测、预警预测、指挥调度、决策支持的全链条安全管理体系。 一…

Linux进程信号(一)之信号的入门

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

基于springboot+vue的机场乘客服务系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat12开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;Maven3.3.9 系统展示 用户管理 航班信…

基于SpringBoot的房屋租赁管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

STM32外设AD/DA-基础及CubeMX配置

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

React Native简介

React Native 是由 Meta&#xff08;原 Facebook&#xff09;开源的跨平台移动应用开发框架&#xff0c;基于 React 和 JavaScript&#xff0c;允许开发者使用同一套代码库构建 iOS 和 Android 原生应用。通过 JavaScript 调用原生组件实现高性能渲染。 跨平台开发 共享 80%-9…

GCC 使用说明

参数 -fPIC ppc_85xx-gcc -shared -fPIC liberr.c -o liberr.so -fPIC 作用于编译阶段&#xff0c;告诉编译器产生与位置无关代码(Position-Independent Code)&#xff0c; 则产生的代码中&#xff0c;没有绝对地址&#xff0c;全部使用相对地址&#xff0c;故而代码可以被加…

Verilog HDL 语言整理

Verilog HDL 语言 Verilog HDL 简介 硬件描述语言Hardware Description Language是一种用形式化方法即文本形式 来描述和设计数字电路和数字系统的高级模块化语言 Verilog HDL&#xff08;Hardware Description Language&#xff09;是一种硬件描述语言&#xff0c;用于建模…

车道线检测----Lane-ATT

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

linux安装宝塔面板到数据盘

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

【基础】Windows开发设置入门7:PowerShell的相关概念和使用

前言 大家熟悉的docker、Python&#xff0c;但对于Windows上有一套开配合开发的相对底层的环境设置&#xff0c;包括powershell、winget、WSL、还有开发驱动器什么的&#xff0c;我准备系统学一下&#xff0c;不然地基不牢&#xff0c;也盖不起冲天高楼~ 本节&#xff0c;介绍…

芯片生态链深度解析(一):基础材料篇——从砂砾到硅基王国的核心技术突围

【开篇&#xff1a;芯片——现代文明的“炼金术”】 当您滑动手机屏幕、驾驶新能源汽车、甚至用AI生成一幅画时&#xff0c;是否想过这些科技奇迹都始于一粒沙子&#xff1f;芯片&#xff0c;这个边长不足2厘米的黑色薄片&#xff0c;正是通过将砂砾提纯为高纯度硅锭&#xff…

一款利用ADB (安卓调试桥)来控制手机的玩机工具

—————【下 载 地 址】——————— 【​本章下载一】&#xff1a;https://drive.uc.cn/s/f36ed8ff62f74 【​本章下载二】&#xff1a;https://pan.xunlei.com/s/VOQDmKCq4u-CygjX9Tcn3fxEA1?pwdwf3t# 【百款黑科技】&#xff1a;https://ucnygalh6wle.feishu.cn/wiki/…

使用mermaid 语言绘画时序图和链路图

给大家展示一下效果&#xff0c; 官方地址&#xff1a;https://mermaid.nodejs.cn/ 官方开发地&#xff1a;https://mermaid.nodejs.cn/intro/#google_vignette graph LR%% 样式定义&#xff08;完全保留&#xff09; classDef user fill:#E1F5FE,stroke:#0288D1;classDef …

浅论3DGS溅射模型在VR眼镜上的应用

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

6种方式来探究数据集的的方法worldquant

覆盖率百分比 指金融数据字段&#xff08;如股价、成交量、财务指标&#xff09;在时间或空间上的有效数据比例。 时间维度&#xff1a;数据在历史周期内的完整度&#xff08;如&#xff1a;某股票过去 1 年中&#xff0c;95% 的交易日有收盘价&#xff09;。空间维度&#xf…

深度学习中的归一化:提升模型性能的关键因素

&#x1f4cc; 友情提示&#xff1a; 本文内容由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;创作平台的gpt-4-turbo模型辅助完成&#xff0c;旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证&#xff0c;建议读者通过官方文档或实践进一步确认…

vue+threeJS 大理石贴图

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

WebGL 3着色器和GLSL

我们之前提到过着色器和GLSL&#xff0c;但是没有涉及细节&#xff0c;你可能已经对此有所了解&#xff0c; 但以防万一&#xff0c;这里将详细讲解着色器和GLSL。 在工作原理中我们提到&#xff0c;WebGL每次绘制需要两个着色器&#xff0c; 一个顶点着色器和一个片段着色器&…