页面置换算法模拟 最近最久未使用(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…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...