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

news2024/11/23 19:52:40

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; // 生成t
    for(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;
        else
            s = (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; // 不缺页置为0
            pagelist[i].time = 0; // 访问记录置0
            if(randBool()) {
                pagelist[i].r = 1;
                pagelist[i].rw = 1;
            }
            else
                pagelist[i].r = 1;
            return true;
        }
    }
    lossflag = 1; // 缺页置为1
    return 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.coloradmin.cn/o/1162024.html

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

相关文章

Jenkins自动化部署相关shell命令

1. 只后台启动&#xff1a; nohup java -jar jar/demo*.jar & 2. 增加命令启动日志输出位置&#xff0c;防止超时处理配置&#xff1a; nohup java -jar /soft/gitee-demo-0.0.1-SNAPSHOT.jar >mylog.log 2>&1 & 简化写法&#xff1a; nohup java -jar /s…

CTF-RSA加密-1

RSA加密算法 RSA算法的具体描述如下&#xff1a; &#xff08;1&#xff09;任意选取两个不同的大素数p和q计算乘积 n p q npq npq &#xff0c; φ ( n ) ( p − 1 ) ( q − 1 ) φ(n)(p-1)(q-1) φ(n)(p−1)(q−1) &#xff1b; &#xff08;2&#xff09;任意选取一个大…

大数据之LibrA数据库系统告警处理(ALM-12010 Manager主备节点间心跳中断)

告警解释 当主Manager节点在7秒内没有收到备Manager节点的心跳信号时&#xff0c;产生该告警。 当主Manager节点收到备Manager节点的心跳信号后&#xff0c;告警恢复。 告警属性 告警参数 对系统的影响 如果主Manager进程异常&#xff0c;主备倒换无法进行&#xff0c;影响…

云主机VNC报错 fork:cannot allocate memory ,也无法SSH

查找解决办法,发现大部分都是因为现有的进程数超过系统设置最大进程数 开始排查: 1.重启系统然后SSH连接(刚启动进程少是可以连上的),查看系统设置的最大进程数: 1.1 执行以下命令,查看系统 pid_max 值。 sysctl -a | grep pid_max根据返回结果,进行对应操作: 返回…

Linux越学越头疼,我要怎么办?

最近&#xff0c;听到一些同学说&#xff0c;“Linux越学越头疼”。其实这句话&#xff0c;在我之前刚接触Linux的时候&#xff0c;也是深有感触。Linux越学越不明所以。最后干脆放弃学习&#xff0c;转而学习其他东西。 其实大家在初学Linux的时候&#xff0c; 有这个感受&am…

Midjourney prompt 大赏(亲测可用)

AI 绘图是什么 AI 绘画&#xff0c;顾名思义就是利用人工智能进行绘画&#xff0c;是人工智能生成内容&#xff08;AIGC&#xff09;的一个应用场景。其主要原理简单来说就是收集大量已有作品数据&#xff0c;通过算法对它们进行解析&#xff0c;最后再生成新作品&#xff0c;…

RocketMQ sql92的使用及原理简单分析附源码

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 RocketMQ 版本 5.1.0 RokcetMQ消息过滤 目前官方支持的消息过滤方式主要有两种 tagsql92 我们可以通过查看ExpressionType的源码证明 tag过滤方式是现在最为…

【计算机网络】(谢希仁第八版)第三章课后习题答案

第三章 1.数据链路(即逻辑链路)与链路(即物理链路)有何区别? “电路接通了”与”数据链路接通了”的区别何在? 答&#xff1a;数据链路与链路的区别在于数据链路出链路外&#xff0c;还必须有一些必要的规程来控制数据的传输&#xff0c;因此&#xff0c;数据链路比链路多了…

不要在不使用cvx优化的场合使用log_det,应改为log(det(..)),否者可能会出现奇怪的错误

跑代码的时候遇到的问题 %% 分解为功率和单位模&#xff0c;交替优化功率分量和单位模clc;clear; Nt 8; % 发射天线数目 8 Nr 4; % 接收天线数目 4 Ne 6; % Eve天线数目 6 noisePower 1; SNRTotaldB -5:5:35; %%%%最大发射功率单位dB SNRTotal 10.^(SNRTotaldB./…

运动耳机品牌排行榜前十名,运动耳机品牌有哪些?

​当你在健身房挥汗如雨&#xff0c;或者在户外享受大自然的时候&#xff0c;最想要的是听歌放松心情&#xff0c;而运动耳机就像一个不知疲倦的伙伴&#xff0c;陪着你度过每一刻。它的稳定性和舒适性在最大程度上保证了你可以专注于你的运动&#xff0c;而不用分心于耳机的位…

基于springboot实现原创歌曲分享平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现原创歌曲分享平台演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理平台应运而生&am…

创建ABAP数据库表和ABAP字典对象-理解表字段02

理解表字段 这一步&#xff0c;您将定义表字段。首先&#xff0c;你需要了解你的需求: 内置的ABAP类型和新定义的字段类型 下面我们将会创建3个字段类型在数据库表中。 ●内置字段类型&#xff1a;最快的方法:应用系统已经提供好的字段类型&#xff0c;基本类型、长度和描述…

AGENTBENCH:评估LLMs作为代理的能力

背景&#xff1a; 这篇文章介绍了他们是如何去构造智能Agent评测集&#xff0c;以及如何对智能Agent能力做了几大分类。如果你无法评测一个问题&#xff0c;那么往往你也不能很好的解决一个问题。评测集的设计往往是更深入本质&#xff0c;因为评测集测试的是更泛化能力&#…

Find My磁吸卡包|苹果Find My技术与磁吸卡包结合,智能防丢,全球定位

2020年苹果发布会上&#xff0c;磁吸卡包应运而生&#xff0c;磁吸卡包可放入银行卡、交通卡等常规卡片&#xff0c;通过磁力轻松吸附在iPhone或MagSafe磁吸保护壳背后&#xff0c;用户轻装出门携带卡片更方便。 在智能化加持下&#xff0c;磁吸卡包加入防丢功能&#xff0c;…

高速光耦合器TLP2361(TPL,E(T 在工业网络中的应用

TLP2361(TPL,E(T 由一个高输出 GaA ℓAs 发光二极管与集成的高增益、高速光电探测器组成。它采用 SO6 封装。 该光电耦合器可保证在高达 125 C 和 2.7 V 至 5.5 V 电源下运行。由于 TLP2361 已保证 1 mA 低电源电流 (ICCL/ICCH) 和 1.6 mA (Ta 125 C) 低阈值输入电流&#xf…

论坛类型知识问答科普源码系统 带完整搭建教程

在互联网上&#xff0c;用户对于获取各类知识的需求不断增长&#xff0c;尤其是对于一些专业性较强或者较为冷门的知识领域。传统的搜索引擎并不能完全满足用户的需求&#xff0c;因此&#xff0c;开发一款针对特定知识领域的问答系统变得尤为重要。今天源码小编来给大家介绍一…

java修仙传之海岛奇遇

昨日开会&#xff0c; 商量了一下接口返回数据&#xff0c; 要求统一&#xff0c; 之前也同意&#xff0c;直接抛异常&#xff0c; 现在觉得之前那个异常不好&#xff0c; 看着不美观&#xff0c;对客户不友好 要求重新做。 大概要求如下&#xff1a; 要求1&#xff1a;范…

公派访问学者申请应该如何选择国家?

选择国家是公派访问学者申请中至关重要的一步。不同国家拥有各自独特的文化、教育体系和研究环境&#xff0c;因此&#xff0c;选择合适的国家对于一个学者的职业生涯和学术发展至关重要。下面将探讨一些选择国家时需要考虑的因素。 首先&#xff0c;你应该考虑自己的研究领域和…

干货 | 一文详解华为ITR流程体系:目标、流程、理念

华为著名的三大流程IPD、LTC、ITR让研发、营销、服务三大板块联动&#xff0c;以客户为中心提供高质量且不断改善的产品和服务。其中ITR大大提升了客服部门的效率和服务水平&#xff0c;还让客服在服务过程中有增加销售的可能。本文详解华为ITR的概念、目标、地位、构成、理念&…

linux编译boost库并执行程序

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、--prefix命令 二、安装过程 1、shell脚本&#xff1a; 2、gcc编译环境 执行过程 三、linux下执行cpp程序 总结 前言 提示&#xff1a;这里可以添加本文…