页面淘汰算法模拟实现与比较

1.实验目标

利用标准C 语言,编程设计与实现最佳淘汰算法、先进先出淘汰算法、最近最久未使用淘汰算法、简单 Clock 淘汰算法及改进型 Clock 淘汰算法,并随机发生页面访问序列开展有关算法的测试及性能比较。

2.算法描述

 1. 最佳淘汰算法(Optimal Replacement Algorithm):这种算法选择将来最久不会被访问的页面进行淘汰。实现这个算法需要预知未来的页面访问请求,因此在实际中无法实现,但是我们可以模拟访问序列来比较实现效果。

2. 先进先出淘汰算法(FIFO Replacement Algorithm):这种算法总是淘汰最早进入内存的页面。实现这个算法可以使用一个队列,新进入的页面放入队尾,需要淘汰页面时总是淘汰队头的页面。

3. 最近最久未使用淘汰算法(LRU Replacement Algorithm):这种算法淘汰最长时间未被访问的页面。实现这个算法可以使用一个链表,每次页面被访问时,将这个页面移动到链表头,需要淘汰页面时总是淘汰链表尾的页面。

4. 简单 Clock 淘汰算法(Clock Replacement Algorithm):这种算法将内存中的页面组织成一个环形链表,有一个指针指向最早进入的页面。每次需要淘汰页面时,检查指针指向的页面,如果这个页面最近被访问过,则将其标记清除,指针向前移动,否则淘汰这个页面。

5. 改进型 Clock 淘汰算法(Enhanced Clock Replacement Algorithm):这是 Clock 算法的改进版,增加了一个修改位用于记录页面是否被修改过。在选择淘汰的页面时,优先选择未被修改且最近未被访问的页面。

3.访问序列模拟 

1. 初始化进程逻辑地址空间页面总数 N、各逻辑页面的读写访问方式(是否支持写访问,即R、RW)、工作集起始页号s(s∈[0, N)) 、工作集中包含的页数 w,工作集移动速率 v(每处理 v 个页面访问,就将工作集起始页号递增即 s+1)以及一个取值区间为[0, 1]的值 t

2. 生成取值区间为[s, min(s+w, N-1)]的v 个随机数并添加保存到页面访问序列中,同时为每次页面访问分别生成一个取值区间为[0, 1]的随机数,若该随机数值大于 0.7 且对应所访问页面支持写访问则设定以写方式访问相应页面,否则以读方式访问对应页面

3. 生成取值区间为[0, 1]的一个随机数r,并比较 r 与t 的大小

4. 若r < t,则为s 生成一个新值(s∈[0, N)) ,否则s = (s + 1) mod N

5. 如果想继续加大页面访问序列的长度,返回第 2 步,否则结束

4.模拟测试思路 

基于相同的条件,系统均采用固定分配局部置换策略、相同的进程逻辑地址空间大小、分配给进程同样多的物理块、相同的页面访问序列、均预装入前三个页面,进行有关算法的测试,预计执行一百轮测试,以轮数为随机数种子,保证结果可以复现。

5.相关数据结构 

// 模拟页面
struct PAGE { int  pages[MAXLEN];int  usenum; // 分配的最大页框数int  visitlen; // 访问序列长度
} pinfo;// 模拟页表
struct MEM { int time; // 访问记录int r; // 访问位int rw; // 修改位int pages; // 页号
} minfo;MEM pagelist[MAXLEN]; // 分配页框
#include <iostream>
#include <thread>
#include <time.h>
using namespace std;const int MAXLEN = 1024; // 最大页面数
const int epoch = 100; // 测试次数
int lossnum; // 缺页次数统计
int now; // 当前访问的页面
int replace; // 页面替换指针
int lossflag; // 是否缺页
int full; // 已使用的页框数
int rate[5][epoch];
int times[5][epoch];struct PAGE {int  pages[MAXLEN];int  usenum; // 分配的最大页框数int  visitlen; // 访问序列长度
} pinfo;
struct MEM {int time; // 访问记录int r; // 访问位int rw; // 修改位int pages; // 页号
} minfo;
MEM pagelist[MAXLEN]; // 分配页框void pageinit() { // 初始化页面数据pinfo.usenum = 3;pinfo.visitlen = 256;for (int i = 0; i < MAXLEN; i++)pinfo.pages[i] = -1;
}void visitlist(int epoch) { // 随机生成访问序列int v = 16, w = 64, s = 128; // v为每个页面访问次数,w为每个页面访问的范围,s为页面访问的起始位置pageinit();srand(epoch); // 随机种子int t= rand() % 11; // 生成tfor(int i = 0, j =0; i < 10; i++) {for(j = i * v; j < (i + 1) * v; j++) { // 生成v个[s, s+w]的随机数if(j > pinfo.visitlen) // 生成数量不能超序列长度break;pinfo.pages[j]= (s + (rand() % w)) % MAXLEN; // 随机数存储到访问序列中}if(rand() % 11 < t) // 如果r < t,则为p生成一个新值s = rand() % MAXLEN;elses = (s + 1) % MAXLEN;}
}bool randBool() { // 读写随机数生成函数if(rand() % 11 > 7) return true;else return false;
}bool inram(int page) { // 查找是否在内存for(int i = 0; i < pinfo.usenum; i++) {pagelist[i].time++;  // 访问记录++}for(int i = 0; i < pinfo.usenum; i++) {if(pagelist[i].pages == page) {lossflag = 0; // 不缺页置为0pagelist[i].time = 0; // 访问记录置0if(randBool()) {pagelist[i].r = 1;pagelist[i].rw = 1;}elsepagelist[i].r = 1;return true;}}lossflag = 1; // 缺页置为1return false;
}void OPT() {// 最佳淘汰算法replace = 0, lossnum = 0, full = 0, lossflag = 0;for(int i = 0; i < pinfo.usenum; i++) // 刷新页框pagelist[i].pages = -1;for(now = 0; now < pinfo.visitlen; now++) {if(full < pinfo.usenum) {if(!inram(pinfo.pages[now])) { // 不在内存则装入页面pagelist[replace].pages = pinfo.pages[now];replace = (replace + 1) % pinfo.usenum;full++, lossnum++; }}else {if(!inram(pinfo.pages[now])) { // 不在内存则需置换int min, max = 0 ; // min为最近访问,max为最远访问for(int m = 0; m < pinfo.usenum ; m++) {min = MAXLEN;for(int n = now; n < pinfo.visitlen; n++) {if (pinfo.pages[n] == pagelist[m].pages) {min = n;break;}}if(max < min) {max = min;replace = m;}}pagelist[replace].pages = pinfo.pages[now];replace = (replace + 1) % pinfo.usenum;lossnum++;}}std::this_thread::sleep_for(10ms);}
}void FIFO(void) { // 先进先出淘汰算法replace = 0, lossnum = 0, full = 0, lossflag = 0;for(int i = 0; i < pinfo.usenum; i++)pagelist[i].pages = -1;for(now = 0; now < pinfo.visitlen; now++) {if(full < pinfo.usenum) { if(!inram(pinfo.pages[now])) {pagelist[replace].pages = pinfo.pages[now];replace = (replace + 1) % pinfo.usenum;full++, lossnum++;}}else {if(!inram(pinfo.pages[now])) {pagelist[replace].pages = pinfo.pages[now];replace = (replace + 1) % pinfo.usenum;lossnum++;}}std::this_thread::sleep_for(10ms);}
}void LRU(void) { // 最近最久未使用淘汰算法replace = 0, lossnum = 0, full = 0, lossflag = 0;for(int i = 0; i < pinfo.usenum; i++) {pagelist[i].pages = -1;pagelist[i].time = 0;} // 刷新页框for(now = 0; now < pinfo.visitlen; now++) {if(full < pinfo.usenum) {if(!inram(pinfo.pages[now])) {pagelist[replace].pages = pinfo.pages[now];replace = (replace + 1) % pinfo.usenum;full++, lossnum++;}}else {if(!inram(pinfo.pages[now])) {int max = 0; // 最久的访问记录for(int i = 1; i < pinfo.usenum; i++) {if(pagelist[i].time > pagelist[max].time) {max = i;}}replace = max;pagelist[replace].pages = pinfo.pages[now];pagelist[replace].time = 0;lossnum++;}}std::this_thread::sleep_for(10ms);}
}int replace0(int num) { // 简单Clock置换for(int i = 0; i < pinfo.usenum; i++) {if(pagelist[(i + num) % pinfo.usenum].r == 0 ) // 找到第一个访问位为0的页面return (i + num) % pinfo.usenum;pagelist[(i + num) % pinfo.usenum].r = 0; // 未找到则将所有访问位置0}for(int i = 0; i < pinfo.usenum; i++) {if(pagelist[(i + num) % pinfo.usenum].r == 0 )return (i + num) % pinfo.usenum;}return 0;
}int replace1(int num) { // 改进的clock置换for(int i = 0; i < pinfo.usenum; i++) {if (pagelist[(i + num) % pinfo.usenum].r == 0 && pagelist[(i + num) % pinfo.usenum].rw == 0) // 先找访问位和修改位都为0的页面return (i + num) % pinfo.usenum;}for(int i = 0; i < pinfo.usenum; i++) {if (pagelist[(i + num) % pinfo.usenum].r == 0 && pagelist[(i + num) % pinfo.usenum].rw == 1) // 再找访问位为0,修改位为1的页面return (i + num) % pinfo.usenum;pagelist[(i + num) % pinfo.usenum].r = 0; // 未找到则将所有访问位置0}for(int i = 0; i < pinfo.usenum; i++) {if (pagelist[(i + num) % pinfo.usenum].r == 0 && pagelist[(i + num) % pinfo.usenum].rw == 0) // 再找访问位和修改位都为0的页面return (i + num) % pinfo.usenum;}for(int i = 0; i < pinfo.usenum; i++) {if (pagelist[(i + num) % pinfo.usenum].r == 0 && pagelist[(i + num) % pinfo.usenum].rw == 1) // 最后找访问位为0,修改位为1的页面return (i + num) % pinfo.usenum;}return 0;
}void CLOCK(int choose) {int num = 0;replace = 0, lossnum = 0, full = 0, lossflag = 0;for(int i = 0; i < pinfo.usenum; i++) {pagelist[i].pages = -1;pagelist[i].rw = 0;pagelist[i].r = 0;pagelist[i].time = 0;}for(now = 0; now < pinfo.visitlen; now++) {if(full < pinfo.usenum) {if(!inram(pinfo.pages[now])) {pagelist[replace].pages = pinfo.pages[now];replace = (replace + 1) % pinfo.usenum;pagelist[replace].r = 1;full++, lossnum++;}}else {if(!inram(pinfo.pages[now])) {if(choose == 1)replace = replace1(num++); // choose=1,改进clock算法else if(choose == 0) // choose=0,简单clock算法replace = replace0(num++); pagelist[replace].pages = pinfo.pages[now];pagelist[replace].r = 1;lossnum++;}}std::this_thread::sleep_for(10ms);}
}void calculate(int i, int j, clock_t start) { // 计算缺页率和运行时间rate[i][j] = (double)(lossnum) * 100 / now;times[i][j] = (double)(clock() - start) / 1000;
}int main() {clock_t start;for(int i = 0; i < epoch; i++) {visitlist(i);start = clock();OPT();calculate(0, i, start);start = clock();FIFO();calculate(1, i, start);start = clock();LRU();calculate(2, i, start);start = clock();CLOCK(0);calculate(3, i, start);start = clock();CLOCK(1);calculate(4, i, start);}for(int i = 0; i < 5; i++) {if(i == 0) printf("OPT:    ");if(i == 1) printf("FIFO:   ");if(i == 2) printf("LRU:    ");if(i == 3) printf("CLOCK:  ");if(i == 4) printf("CLOCK+: ");int avrate = 0, avtime = 0;for(int j = 0; j < epoch; j++) {avrate += rate[i][j];avtime += times[i][j];}printf("Average replace rate = %.3lf%%  ", (double)(avrate) / epoch);printf("Average spend time: %.3lfs\n", (double)(avtime) / epoch);}return 0;
}

7.运行结果

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

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

相关文章

Redis与Mysql的数据一致性(双写一致性)

双写一致性&#xff1a;当修改了数据库的数据也要同时的更新缓存的数据&#xff0c;使缓存和数据库的数据要保持一致。 一般是在写数据的时候添加延迟双删的策略 先删缓存 再修改数据 延迟一段时间后再次删除缓存 这种方式其实不是很靠谱 一致性要求高 共享锁&#xff1a;读…

制作网页版H5页面商城源码系统+随心DIY 带前后端完整搭建教程

随着智能手机的广泛普及&#xff0c;人们越来越依赖手机进行日常生活中的各种活动&#xff0c;包括购物。传统的PC端购物模式已经无法满足人们的需求&#xff0c;因此开发移动端的购物系统势在必行。而现如今H5技术不断发展成熟&#xff0c;使得在手机等移动设备上展示网页版商…

vue-cli5.0.x优雅降级,配置项目兼容旧版浏览器

兼容低版本谷歌浏览器 vue-cli5.0.x脚手架下的&#xff0c;如何降低项目版本以适用于底版本的浏览器。 直接使用默认配置打包部署出来的项目再40&#xff0c;60、70版本的谷歌浏览器跑不起来&#xff0c;蓝屏或者浏览器白屏一般这种情况都需要通过Babel去做转换&#xff0c;我…

数据库概论

目录 什么是数据库数据库的概念模型层次模型网状模型关系模型 为什么要使用关系型数据库完整性约束结构化查询语言SQL基本语句 什么是数据库 考虑这些问题&#xff1a;当用户使用软件计算时&#xff0c;如果想要保存计算结果或者想选择不同的题目&#xff0c;是否要保存、读取…

爱写bug的小邓程序员个人博客

博客网址: http://www.006969.xyz 欢迎来到我的个人博客&#xff0c;这里主要分享我对于前后端相关技术的学习笔记、项目实战经验以及一些技术感悟。 在我的博客中&#xff0c;你将看到以下主要内容&#xff1a; 技术文章 我将会分享我在学习前后端技术过程中的一些感悟&am…

解决在Win7下运行一些老游戏花屏或色彩异常问题的方法

有一些喜欢回顾经典老游戏的玩家们&#xff0c;在目前最新的windows7的操作系统下&#xff0c;运行某些游戏会出现花屏&#xff0c;问题的原因是因为win7对这些游戏的DirectDraw不兼容&#xff0c;一种方法是改游戏配置文件&#xff0c;把游戏色彩8bit改成16bit&#xff0c;当然…

数据仓库-拉链表

在数据仓库中制作拉链表&#xff0c;可以按照以下步骤进行&#xff1a; 确定需求&#xff1a;首先明确需要使用拉链表的场景和需求。例如&#xff0c;可能需要记录历史数据的变化&#xff0c;以便进行时间序列分析等。设计表结构&#xff1a;在数据仓库中&#xff0c;拉链表通…

Tomcat下载地址(详细)

Apache Tomcat - Apache Tomcat 8 Software Downloadshttps://tomcat.apache.org/download-80.cgi2.找到Archives 3.选择下载的把版本 4.选择具体下载那个版本 5. 6.一般选择tar.gz结尾的压缩包

R语言的DICE模型实践技术

随着温室气体排放量的增大和温室效应的增强&#xff0c;全球气候变化问题受到日益的关注。我国政府庄严承诺在2030和2060年分别达到“碳达峰”和“碳中和”&#xff0c;因此气候变化和碳排放已经成为科研人员重点关心的问题之一。气候变化问题不仅仅是科学的问题&#xff0c;同…

Android问题

这里面要加入 ,加入前是点击待君登录直接跳回手机主界面了 加入上述代码即可 Android之Inflate() Inflate()作用就是将xml定义的一个布局找出来&#xff0c;但仅仅是找出来而且隐藏的&#xff0c;没有找到的同时并显示功能。 android上还有一个与Inflate()类似功能的…

《异常检测——从经典算法到深度学习》23 TimesNet: 用于常规时间序列分析的时间二维变化模型

zz# 《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Don…

el-table动态增加列、行数据,俩种方法实现按需选择

需求&#xff1a; 表格数据过多的时候&#xff0c;需要实现动态选择数据的功能&#xff0c;有俩种方法可以按需选择&#xff0c;解决了表格动态选择时闪屏数据抖动问题。 注意&#xff0c;这个添加数据是tableData原本就有的&#xff0c;我做的这个操作类似就是折叠选择展示原有…