页面置换算法模拟 最近最久未使用(LRU)算法
最近最久未使用(LRU)算法是一种基于页面访问历史的页面置换算法。它选择最久未使用的页面进行置换。当需要访问一个不在内存中的页面时,如果内存已满,则选择最久未使用的页面进行置换。LRU算法通过记录页面的访问时间戳来判断页面的使用频率。
最优(OPT)算法是一种理论上的最优页面置换算法,但在实际系统中难以实现。它基于未来的页面访问序列来选择最佳的置换页面。OPT算法假设系统能够预知未来的页面访问情况,从而选择在未来最长时间内不会被访问的页面进行置换。由于OPT算法需要预知未来的信息,因此在实际系统中无法应用。
缺页率是指在处理页面访问过程中进行页面置换的频率。在本实验中,我们可以通过统计每次页面访问时是否发生缺页来计算缺页率。具体地,当需要访问一个不在内存中的页面时,如果内存已满,则需要进行页面置换,此时发生一次缺页;如果内存未满,则直接将页面加载到内存中,不发生缺页。通过统计每次页面访问时的缺页次数,我们可以计算出不同页面置换算法在不同内存容量下的缺页率,并据此评估其性能表现。
LRU页面置换算法的流程可以简单描述如下:
1、随机生成页面引用:首先随机生成一系列的页面引用,这些页面引用代表了进程请求访问的页面序号。在本例中,我们生成了10个0到7之间的随机页面序号。
2、用户输入物理块个数:接下来,系统提示用户输入进程被分配的物理块个数,即内存中可以同时容纳的页面数量。用户输入的数值应当是一个合理的值,通常不超过系统定义的最大页面总数。
3、初始化物理块状态数组:根据用户输入的物理块个数,我们初始化一个物理内存块数组,用于模拟内存中的物理块。每个帧都包含一个页面号和一个时间值,分别表示当前帧中存储的页面序号和该页面最近一次被放入内存中的时间。
4、页面置换:对于每个页面引用,我们检查它是否已经在内存中(即帧数组中是否有匹配的页面号)。如果在,则继续处理下一个页面引用;如果不在,则发生页面错误(缺页),我们需要从内存中选择一个页面进行置换。LRU算法选择最近最少使用的页面进行置换,即找到最长时间未被访问的页面,并将其从内存中移除,然后将新的页面引用加载到空闲的帧中。
缺页率计算:在整个页面引用序列处理完毕后,我们统计页面错误的次数,并计算缺页率。缺页率是页面错误次数与总页面引用次数的比值,它反映了内存管理策略的效率。缺页率越低,表示内存管理策略越有效。
代码实现部分:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#define MAX_PAGES 8 //假设页面总数为8
#define MAX_REFERENCES 10 //假设随机生成10个页面引用
int pageFaultsNum = 0;//页面错误 (缺页)计数
int pageReplaceNum = 0;//页面置换次数//也框结构体,用于存储页面号和调入内存的时间
typedef struct
{
int pageNumber;
int time;
} Frame;//初始化页框数组
void initializeFrames(Frame frames[],int maxFrames)
{
for(int i = 0;i < maxFrames; i++)
{
frames[i].pageNumber = -1;//初始时页面号为-1,表示空闲
frames[i].time = -1;//最近依次被放入物理块的时间
}
}//生成0~9之间的随机页面序号
int genRandomPage()
{
return rand() % MAX_PAGES;
}//LEU页面置换算法,并计算缺页率
double lruPageReplacement(Frame frames[], int maxFrames, int referenceString[],int length)
{
int frameFull = 0;//物理块已被装入个数
pageFaultsNum = 0;//页面错误(缺页)计数清零
pageReplaceNum = 0;//页面置换次数清零
for(int i = 0;i < length; i++)
{
bool found = false;//标记页面是否在内存中
int j = 0;
for(j = 0;j< maxFrames;j++)
{
if (frames[j].pageNumber == referenceString[i])
{
found = true;//如果找到,则标记为已经找到,跳出循环
break;
}
}
//如果页面不在内存中,则发生页面错误(缺页),需要调入内存
if(!found)
{
pageFaultsNum++;//把缺页次数+1
if(frameFull<maxFrames)//物理块未满,可直接将页面装入
{
frames[frameFull].pageNumber = referenceString[i];
frames[frameFull].time = i;
frameFull++;
}
else//物理块已装满,需要置换一页出去
{
int smallTime = MAX_REFERENCES;
int lruFrame = -i;
for(int j = 0;j < maxFrames;j++)//遍历锁业物理块,选出时间最早的哪那个页面
{
if(frames[j].time < smallTime)
{
smallTime = frames[j].time;
lruFrame = j;
}
}
//替换最近最久未使用的帧,新页号直接写入内存块中,并更新时间
frames[lruFrame].pageNumber = referenceString[i];
frames[lruFrame].time = i;
pageReplaceNum++;//置换次数加1
}
}
else
{//该页已在内存,只需要更新一下使用时间
frames[j].time = i;
}
}
//计算缺页率
printf("\n页面缺页次数为:%d\n",pageFaultsNum);
printf("页面置换次数为:%d\n",pageReplaceNum);
double pageFaultRate = (double)pageFaultsNum / length;return pageFaultRate;
}int main()
{
while(1)
{
srand(time(NULL));//初始化随机数生成器
int referenceString[MAX_REFERENCES];//存储随机生成的页面引用
for(int i = 0;i< MAX_REFERENCES;i++)
referenceString[i] = genRandomPage();//生成随机页面序号int maxFrames;//进程被分配的物理块个数
printf("请输入进程被分配的物理块个数(不超过%d):",MAX_PAGES);
scanf("%d",&maxFrames);printf("随机生成的页面引用序列为:");
for(int i = 0;i <MAX_REFERENCES;i++)
printf("%d ",referenceString[i]);if(maxFrames <= 0|| maxFrames > MAX_PAGES)
{
printf("输入的物理块的个数无效,请输入1到%d之间的整数。\n",MAX_PAGES);
return 1;
}
Frame frames[maxFrames];//初始化页框数组
initializeFrames(frames,maxFrames);//调用LRU页面置换算法并计算缺页率
double pageFaultRate = lruPageReplacement(frames,maxFrames,referenceString,MAX_REFERENCES);
//输出结果
printf("缺页率为:%.2f%%\n\n",pageFaultRate * 100);
}
return 0;
}
运行结果:
在原设置(页面总数8,页面引用序列10)的基础上,将物理块数设为3。

手动推导缺页和置换的过程:
| 7 | 2 | 5 | 5 | 5 | 5 | 1 | 6 | 5 | 0 | |
| 1 | 7 | 7 | 7 | 7 | 7 | 7 | 1 | 1 | 1 | 0 |
| 2 | 2 | 2 | 2 | 2 | 2 | 2 | 6 | 6 | 6 | |
| 3 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | ||
| 是否缺页 | 缺缺 | 缺缺 | 缺缺 | 缺缺 | 缺缺 | 缺缺 |
缺页率: 6 / 10 = 60%
在原设置(页面总数8,页面引用序列10)的基础上,将物理块数设为5。

并手动推导缺页置换的过程,验证缺页率结果是否正确:
| 7 | 0 | 0 | 1 | 1 | 0 | 2 | 4 | 7 | 7 | |
| 1 | 7 | 7 | 7 | 7 | 7 | 7 | 7 | 7 | 7 | 7 |
| 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
| 3 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | |||
| 4 | 2 | 2 | 2 | 2 | ||||||
| 5 | 4 | 4 | 4 | |||||||
| 是否缺页 | 缺 | 缺 | 缺 | 缺 | 缺 |
缺页率:5 / 10 = 50%
修改代码,使得页面总数为10,页面序列为20,设定物理块数为3。


并手动推导缺页置换的过程,验证缺页率结果是否正确:
| 9 | 4 | 8 | 9 | 3 | 6 | 2 | 0 | 1 | 8 | 8 | 0 | 0 | 2 | 2 | 8 | 8 | 8 | 2 | 9 | |
| 1 | 9 | 9 | 9 | 9 | 9 | 9 | 2 | 2 | 2 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 |
| 2 | 4 | 4 | 4 | 3 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 9 | |
| 3 | 8 | 8 | 8 | 6 | 6 | 6 | 1 | 1 | 1 | 1 | 1 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | ||
| 是否缺页 | 缺 | 缺 | 缺 | 缺 | 缺 | 缺 | 缺 | 缺 | 缺 | 缺 | 缺 |
缺页率:11 / 20 = 55%
相关文章:
页面置换算法模拟 最近最久未使用(LRU)算法
最近最久未使用(LRU)算法是一种基于页面访问历史的页面置换算法。它选择最久未使用的页面进行置换。当需要访问一个不在内存中的页面时,如果内存已满,则选择最久未使用的页面进行置换。LRU算法通过记录页面的访问时间戳来判断页面…...
Ubuntu与Centos系统有何区别?
Ubuntu和CentOS都是基于Linux内核的操作系统,但它们在设计理念、使用场景和技术实现上有显著的区别。以下是详细的对比: 1. 基础和发行版本 Ubuntu: 基于Debian,使用.deb包管理系统。包含两个主要版本: LTSÿ…...
RK3568平台开发系列讲解(pinctrl 子系统篇)pinctrl_debug
🚀返回专栏总目录 文章目录 1. Overview2. debug信息2.1 pinctrl-devices2.2. pinctrl-handles2.3. pinctrl-handles3. debug信息3.1. 查看(pinctrl_register_pins)注册了哪些pins3.2. 查看pin groups;3.3. 查看每种functions所占用的gpio groups信息:3.4. pinconf沉淀、…...
避大坑!Vue3中reactive丢失响应式的问题
在vue3中,我们定义响应式数据无非是ref和reactive。 但是有的小伙伴会踩雷!导致定义的响应式丢失的问题。 reactive丢失响应式的情况1(直接赋值) 场景: 1.你定义了一个数据:let datareactive({name:"",age:"" }) 2.然后你…...
springSecurity权限控制
权限控制:不同的用户可以使用不同的功能。 我们不能在前端判断用户权限来控制显示哪些按钮,因为这样,有人会获取该功能对应的接口,就不需要通过前端,直接发送请求实现功能了。所以需要在后端进行权限判断。࿰…...
Pytorch训练固定随机种子(单卡场景和分布式训练场景)
模型的训练是一个随机过程,固定随机种子可以帮助我们复现实验结果。 接下来介绍一个模型训练过程中固定随机种子的代码,并对每条语句的作用都会进行解释。 def seed_reproducer(seed2333):random.seed(seed)os.environ["PYTHONHASHSEED"] s…...
Conda + JuiceFS :增强 AI 开发环境共享能力
Conda 是当前 AI 应用开发领域中非常流行的环境和包管理系统,因其能够简单便捷地创建与系统资源相隔离的虚拟环境广受欢迎。 Conda 支持在不同的操作系统上重建相同的工作环境,但在环境共享复用方面仍存在一些挑战。比如,在不同机器上复用相…...
人工智能-人机交互的机会
目录 引言HCI领域的发展机会人工智能领域的崛起与机会博雅智信的HCI与AI辅导服务结语 引言 在人类科技不断进步的今天,HCI(人机交互)和人工智能(AI)是两个密切相关且充满潜力的领域。HCI研究如何优化人类与计算机之间…...
【系统架构核心服务设计】使用 Redis ZSET 实现排行榜服务
目录 一、排行榜的应用场景 二、排行榜技术的特点 三、使用Redis ZSET实现排行榜 3.1 引入依赖 3.2 配置Redis连接 3.3 创建实体类(可选) 3.4 编写 Redis 操作服务层 3.5 编写控制器层 3.6 测试 3.6.1 测试 addMovieScore 接口 3.6.2 测试 g…...
elasticsearch基础总结
最近实习,项目用的elasticseatch做的存储库,但是之前对于es接触的不多,查询语法有些不熟,每次想写个DSL查询时都要gpt或者施展搜索大法,所以索性就自己总结总结,以后忘了也方便查。所以这篇文章会持续更新。…...
【慕伏白教程】Zerotier 连接与简单配置
文章目录 下载与安装WindowsLinuxapt安装官方脚本安装 Zerotier 配置新建网络网络配置 终端配置WindowsLinux 下载与安装 Windows 进入Zerotier官方下载网站,点击下载 在下载目录找到安装文件,双击打开后点击 Install 开始安装 安装完成后,…...
Brain.js(九):LSTMTimeStep 实战教程 - 未来短期内的股市指数预测 - 实操要谨慎
系列的前一文RNNTimeStep 实战教程 - 股票价格预测 讲述了如何使用RNN时间序列预测实时的股价, 在这一节中,我们将深入学习如何利用 JavaScript 在浏览器环境下使用 LSTMTimeStep 进行股市指数的短期预测。通过本次实战教程,你将了解到如何用…...
C# 字符串(String)
文章目录 前言创建 String 对象的方式1. 通过给 String 变量指定一个字符串2. 通过使用 String 类构造函数3. 通过使用字符串串联运算符( )4. 通过检索属性或调用一个返回字符串的方法5. 通过格式化方法来转换一个值或对象为它的字符串表示形式 String …...
二进制文件
大多数人听到“二进制”的时候,脑海里可能马上就会联想到电影《黑客帝国》中由“0”和“1”组成的矩阵。 笔者不打算在这里详细讨论二进制的运算、反码、补码之类枯燥的东西,但有几个和开发相关的概念需要做一点澄清和普及。因为这些内容就像空气——用…...
【电子元器件】音频功放种类
本文章是笔者整理的备忘笔记。希望在帮助自己温习避免遗忘的同时,也能帮助其他需要参考的朋友。如有谬误,欢迎大家进行指正。 一、概述 音频功放将小信号的幅值提高至有用电平,同时保留小信号的细节,这称为线性度。放大器的线性…...
linux之vim
一、模式转换命令 vim主要有三种模式:命令模式(Normal Mode)、输入模式(Insert Mode)和底线命令模式(Command-Line Mode)。 从命令模式切换到输入模式:i:在当前光标所在…...
QT的ui界面显示不全问题(适应高分辨率屏幕)
//自动适应高分辨率 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);一、问题 电脑分辨率高,默认情况下,打开QT的ui界面,显示不全按钮内容 二、解决方案 如果自己的电脑分辨率较高,可以尝试以下方案:自…...
数据结构--串、数组和广义表
串 定义:串(String)是由零个或多个字符组成的有限序列。 子串:串中任意个连续字符组成的子序列称为该串的子串。 主串:包含子串的串相应地称为主串。 字符位置:字符在该序列中的序号为该字符在串中的位置…...
LLMs之Agent之Lares:Lares的简介、安装和使用方法、案例应用之详细攻略
LLMs之Agent之Lares:Lares的简介、安装和使用方法、案例应用之详细攻略 导读:这篇博文介绍了 Lares,一个由简单的 AI 代理驱动的智能家居助手模拟器,它展现出令人惊讶的解决问题能力。 >> 背景痛点:每天都有新的…...
1-1.mysql2 之 mysql2 初识(mysql2 初识案例、初识案例挖掘)
一、mysql2 概述 mysql2 是一个用于 Node.js 的 MySQL 客户端库 mysql2 是 mysql 库的一个改进版本,提供了更好的性能和更多的功能 使用 mysql2 之前,需要先安装它 npm install mysql2 二、mysql2 初识案例 1、数据库准备 创建数据库 testdb CREAT…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
