FIFO和LRU算法实现操作系统中主存管理

ops/2024/11/25 10:13:29/

FIFO,用数组实现

1和2都是使用nextReplace实现新页面位置的更新

1、不精确时间:用ctime输出运行时间都是0.00秒

#include <iostream>
#include <iomanip>
#include<ctime>//用于计算时间
using namespace std;// 页访问顺序
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };// FIFO算法
void fifo(int n) {int memory[5] = { -1, -1, -1, -1, -1 };  // 用于存储主存块,初始化为 -1 表示空int table[5][20] = { -1 };               // 用于记录每次访问的内存状态,初始化为 -1 表示空bool status[20];                         // 记录是否缺页int pageFaults = 0;                      // 缺页次数int nextReplace = 0;                     // 记录下一个要替换的位置// 获取开始时间(时钟周期数)clock_t start = clock();// 遍历每个页面访问for (int j = 0; j < 20; j++) {int page = pages[j];bool found = false;// 检查页面是否已在内存中for (int i = 0; i < n; i++) {if (memory[i] == page) {found = true;break;}}if (!found) {  // 缺页情况memory[nextReplace] = page;       // 替换页面nextReplace = (nextReplace + 1) % n; // 更新替换位置status[j] = false;                // 标记缺页pageFaults++;}else {status[j] = true;                 // 标记命中}// 记录当前内存状态到表格for (int i = 0; i < n; i++) {table[i][j] = memory[i];}}// 获取结束时间(时钟周期数)clock_t end = clock();// 输出结果表格cout << "主存块号 ";for (int j = 0; j < 20; j++) {cout << pages[j] << " ";}cout << endl;for (int i = 0; i < n; i++) {cout << "   " << i << "     ";for (int j = 0; j < 20; j++) {if (table[i][j] == -1) {cout << "  ";  // 空块显示为空格}else {cout << table[i][j] << " ";}}cout << endl;}// 输出缺页标记cout << "是否缺页 ";for (int j = 0; j < 20; j++) {if (status[j]) {cout << "\u221A ";  // Unicode "√"}else {cout << "\u00D7 ";  // Unicode "×"}}cout << endl;cout << "FIFO 缺页率: " << fixed << setprecision(2) << (float)pageFaults / 20 * 100 << "%" << endl;cout << "运行时间: " << (double)(end - start) / CLOCKS_PER_SEC << " 秒" << endl; // 输出运行时间
}int main() {cout << "内存容量为 3 块:\n";fifo(3);cout << endl;cout << "内存容量为 4 块:\n";fifo(4);return 0;
}

2、精确时间:用chrono输出运行时间都是xx微秒,输出时间不定

#include <iostream>
#include <iomanip>
#include <chrono> // 引入chrono库using namespace std;
using namespace std::chrono; // 使用chrono命名空间// 页访问顺序
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };// FIFO算法
void fifo(int n) {int memory[5] = { -1, -1, -1, -1, -1 };  // 用于存储主存块,初始化为 -1 表示空int table[5][20] = { -1 };               // 用于记录每次访问的内存状态,初始化为 -1 表示空bool status[20];                         // 记录是否缺页int pageFaults = 0;                      // 缺页次数int nextReplace = 0;                     // 记录下一个要替换的位置// 获取开始时间auto start = high_resolution_clock::now();// 遍历每个页面访问for (int j = 0; j < 20; j++) {int page = pages[j];bool found = false;// 检查页面是否已在内存中for (int i = 0; i < n; i++) {if (memory[i] == page) {found = true;break;}}if (!found) {  // 缺页情况memory[nextReplace] = page;       // 替换页面nextReplace = (nextReplace + 1) % n; // 更新替换位置status[j] = false;                // 标记缺页pageFaults++;}else {status[j] = true;                 // 标记命中}// 记录当前内存状态到表格for (int i = 0; i < n; i++) {table[i][j] = memory[i];}}// 获取结束时间auto stop = high_resolution_clock::now();auto duration = duration_cast<microseconds>(stop - start);// 输出结果表格cout << "主存块号 ";for (int j = 0; j < 20; j++) {cout << pages[j] << " ";}cout << endl;for (int i = 0; i < n; i++) {cout << "   " << i << "     ";for (int j = 0; j < 20; j++) {if (table[i][j] == -1) {cout << "  ";  // 空块显示为空格}else {cout << table[i][j] << " ";}}cout << endl;}// 输出缺页标记cout << "是否缺页 ";for (int j = 0; j < 20; j++) {if (status[j]) {cout << "\u221A ";  // Unicode "√"}else {cout << "\u00D7 ";  // Unicode "×"}}cout << endl;cout << "FIFO 缺页率: " << fixed << setprecision(2) << (float)pageFaults / 20 * 100 << "%" << endl;cout << "运行时间: " << duration.count() << " 微秒" << endl; // 输出运行时间
}int main() {cout << "内存容量为 3 块:\n";fifo(3);cout << endl;cout << "内存容量为 4 块:\n";fifo(4);return 0;
}

3、数组模拟队列、类似滑动窗口

#include <iostream>
#include <iomanip>
#include <chrono>
#include <cstring>using namespace std;
using namespace std::chrono;const int N = 1010;
int memory[N];//每次查找页面进行记录的滑动窗口
int table[5][20]; // 最终输出的表格状态
// 页访问顺序
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };// FIFO算法
void fifo(int n) {memset(memory, 0x3f, sizeof memory);bool status[20];  // 记录是否缺页int pageFaults = 0;       // 缺页次数int hh = 0, tt = -1;      // 队首和队尾指针auto start = high_resolution_clock::now(); // 获取开始时间for (int j = 0; j < 20; j++) {int page = pages[j];bool found = false;// 检查页面是否已在内存中for (int i = hh; i <= tt; i++) {if (memory[i] == page) {found = true;break;}}if (!found) {  // 缺页情况memory[++tt] = page; // 新页面加入队尾// 控制滑动窗口大小为 nif (tt - hh + 1 > n) {hh++; // 超过容量,队首出队}status[j] = false;  // 标记缺页pageFaults++;}else {status[j] = true;   // 标记命中}// 记录当前内存状态到表格for (int i = 0; i < n; i++) {//如果只写memory[hh]的话不就移动队首指针了吗,不可以,现在是赋值阶段,只需要控制负责赋值的滑动指针首先不能超过队尾指针,确保在滑动窗口范围内,//因为有可能这个滑动窗口不足n长,你就会多余赋值本来不能存在的页面号赋值成0x3f,其次需要满足当前检查是否缺页的一次记录memory,该位置是否有值if (i + hh <= tt && memory[i + hh] != 0x3f) {table[i][j] = memory[i + hh];}else {table[i][j] = -1; // 空位显示为 -1}}}auto stop = high_resolution_clock::now(); // 获取结束时间auto duration = duration_cast<microseconds>(stop - start);// 输出结果表格cout << "主存块号 ";for (int j = 0; j < 20; j++) {cout << pages[j] << " ";}cout << endl;for (int i = 0; i < n; i++) {cout << "   " << i << "     ";for (int j = 0; j < 20; j++) {if (table[i][j] == -1) {cout << "  ";  // 空块显示为空格}else {cout << table[i][j] << " ";}}cout << endl;}// 输出缺页标记cout << "是否缺页 ";for (int j = 0; j < 20; j++) {cout << (status[j] ? "\u221A " : "\u00D7 ");//unicode编码,前者代表true则不缺页是√标识,后者代表false是缺页×表示}cout << endl;cout << "FIFO 缺页率: " << fixed << setprecision(2) << (float)pageFaults / 20 * 100 << "%" << endl;cout << "运行时间: " << duration.count() << " 微秒" << endl;
}int main() {cout << "内存容量为 3 块:\n";fifo(3);cout << endl;cout << "内存容量为 4 块:\n";fifo(4);return 0;
}

朴素版算缺页率

#include <iostream>
#include <ctime>
#include <cstring>using namespace std;const int N = 1010;
int memory[N];//每次查找页面进行记录的滑动窗口
int table[5][20]; // 最终输出的表格状态
// 页访问顺序
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };// FIFO算法
void fifo(int n) {memset(memory, 0x3f, sizeof memory);bool status[20];  // 记录是否缺页int pageFaults = 0;       // 缺页次数int hh = 0, tt = -1;      // 队首和队尾指针clock_t start=clock(); // 获取开始时间for (int j = 0; j < 20; j++) {int page = pages[j];bool found = false;// 检查页面是否已在内存中for (int i = hh; i <= tt; i++) {if (memory[i] == page) {found = true;break;}}if (!found) {  // 缺页情况memory[++tt] = page; // 新页面加入队尾// 控制滑动窗口大小为 nif (tt - hh + 1 > n) {hh++; // 超过容量,队首出队}status[j] = false;  // 标记缺页pageFaults++;}else {status[j] = true;   // 标记命中}// 记录当前内存状态到表格for (int i = 0; i < n; i++) {//如果只写memory[hh]的话不就移动队首指针了吗,不可以,现在是赋值阶段,只需要控制负责赋值的滑动指针首先不能超过队尾指针,确保在滑动窗口范围内,//因为有可能这个滑动窗口不足n长,你就会多余赋值本来不能存在的页面号赋值成0x3f,其次需要满足当前检查是否缺页的一次记录memory,该位置是否有值if (i + hh <= tt && memory[i + hh] != 0x3f) {table[i][j] = memory[i + hh];}else {table[i][j] = -1; // 空位显示为 -1}}}clock_t end = clock(); // 获取结束时间// 输出结果表格cout << "主存块号 ";for (int j = 0; j < 20; j++) {cout << pages[j] << " ";}cout << endl;for (int i = 0; i < n; i++) {cout << "   " << i << "     ";for (int j = 0; j < 20; j++) {if (table[i][j] == -1) {cout << "  ";  // 空块显示为空格}else {cout << table[i][j] << " ";}}cout << endl;}// 输出缺页标记cout << "是否缺页 ";for (int j = 0; j < 20; j++) {cout << (status[j] ? "\u221A " : "\u00D7 ");//unicode编码,前者代表true则不缺页是√标识,后者代表false是缺页×表示}cout << endl;cout << "FIFO 缺页率: " << (float)pageFaults / 20 * 100 << "%" << endl;cout << "运行时间: " << (double)(end-start)/CLOCKS_PER_SEC << " 秒" << endl;}int main() {cout << "内存容量为 3 块:\n";fifo(3);cout << endl;cout << "内存容量为 4 块:\n";fifo(4);return 0;
}

FIFO,用链表实现

LRU,用计数器实现

#include <iostream>
#include <ctime>
#include <cstring>
#include <unordered_map>using namespace std;const int N = 1010;
int table[5][20]; // 最终输出的表格状态
unordered_map<int, int> m; // 键为page号,值为count值
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };void lru(int n) {memset(table, -1, sizeof table);m.clear();bool status[20]; // 记录是否缺页int pageFaults = 0; // 缺页次数clock_t start = clock(); // 获取开始时间for (int j = 0; j < 20; j++) {int page = pages[j];if (!m.count(page)) { // 没命中就要加入或者替换页面if (m.size() >= n) {// 找到count最大的页面进行替换int maxpage = -1, maxcounts = -1;for (auto p : m) {if (p.second > maxcounts) {maxpage = p.first;maxcounts = p.second;}}m.erase(maxpage);}m[page] = 0;//没命中且主存没满则直接加入页面pageFaults++;status[j] = false; // 标记缺页}else {status[j] = true; // 标记命中m[page] = 0;}// 更新所有页面的count值:命中则置0,没命中加入新页面——满足条件则不加1即可,不管加不加入新页面,其他没中的页面都是要count+1的for (auto& p : m) {if (p.first != page) {p.second += 1;}}// 更新当前主存块内存在的页面int i = 0;for (auto p : m) {if (i < n) {//用一个i去便利贮存块,而不用fortable[i][j] = p.first;i++;}}//一开始写错了:/*for (int i = 0; i < n; i++) {for (auto p : m) {table[i][j] = p.first;}}*/}clock_t end = clock(); // 获取结束时间// 输出结果表格cout << "主存块号 ";for (int j = 0; j < 20; j++) {cout << pages[j] << " ";}cout << endl;for (int i = 0; i < n; i++) {cout << "   " << i << "     ";for (int j = 0; j < 20; j++) {if (table[i][j] == -1) {cout << "  "; // 空块显示为空格}else {cout << table[i][j] << " ";}}cout << endl;}// 输出缺页标记cout << "是否缺页 ";for (int j = 0; j < 20; j++) {cout << (status[j] ? "\u221A " : "\u00D7 ");}cout << endl;cout << "LRU 缺页率: " << (float)(pageFaults) / 20 * 100 << "%" << endl;cout << "运行时间: " << (double)(end - start) / CLOCKS_PER_SEC << " 秒" << endl;
}int main() {cout << "内存容量为 3 块:\n";lru(3);cout << endl;cout << "内存容量为 4 块:\n";lru(4);return 0;
}

LRU,用堆栈实现

两个算法综合在一起看运行速率

#include <iostream>
#include <ctime>
#include <cstring>
#include <unordered_map>
#include <chrono> // 引入chrono库using namespace std;
using namespace std::chrono; // 使用chrono命名空间const int N = 1010;
int table[5][20]; // 最终输出的表格状态
unordered_map<int, int> m; // 键为page号,值为count值
int pages[20] = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };
int memory[N];//每次查找页面进行记录的滑动窗口// FIFO算法
void fifo(int n) {memset(memory, 0x3f, sizeof memory);memset(table, -1, sizeof table);bool status[20];  // 记录是否缺页int pageFaults = 0;       // 缺页次数int hh = 0, tt = -1;      // 队首和队尾指针//clock_t start = clock(); // 获取开始时间// 获取开始时间auto start = high_resolution_clock::now();for (int j = 0; j < 20; j++) {int page = pages[j];bool found = false;// 检查页面是否已在内存中for (int i = hh; i <= tt; i++) {if (memory[i] == page) {found = true;break;}}if (!found) {  // 缺页情况memory[++tt] = page; // 新页面加入队尾// 控制滑动窗口大小为 nif (tt - hh + 1 > n) {hh++; // 超过容量,队首出队}status[j] = false;  // 标记缺页pageFaults++;}else {status[j] = true;   // 标记命中}// 记录当前内存状态到表格for (int i = 0; i < n; i++) {//如果只写memory[hh]的话不就移动队首指针了吗,不可以,现在是赋值阶段,只需要控制负责赋值的滑动指针首先不能超过队尾指针,确保在滑动窗口范围内,//因为有可能这个滑动窗口不足n长,你就会多余赋值本来不能存在的页面号赋值成0x3f,其次需要满足当前检查是否缺页的一次记录memory,该位置是否有值if (i + hh <= tt && memory[i + hh] != 0x3f) {table[i][j] = memory[i + hh];}else {table[i][j] = -1; // 空位显示为 -1}}}//clock_t end = clock(); // 获取结束时间// 获取结束时间auto stop = high_resolution_clock::now();auto duration = duration_cast<microseconds>(stop - start);// 输出结果表格cout << "主存块号 ";for (int j = 0; j < 20; j++) {cout << pages[j] << " ";}cout << endl;for (int i = 0; i < n; i++) {cout << "   " << i << "     ";for (int j = 0; j < 20; j++) {if (table[i][j] == -1) {cout << "  ";  // 空块显示为空格}else {cout << table[i][j] << " ";}}cout << endl;}// 输出缺页标记cout << "是否缺页 ";for (int j = 0; j < 20; j++) {cout << (status[j] ? "\u221A " : "\u00D7 ");//unicode编码,前者代表true则不缺页是√标识,后者代表false是缺页×表示}cout << endl;cout << "FIFO 缺页率: " << (float)pageFaults / 20 * 100 << "%" << endl;//cout << "运行时间: " << (double)(end - start) / CLOCKS_PER_SEC << " 秒" << endl;cout << "运行时间: " << duration.count() << " 微秒" << endl; // 输出运行时间}
void lru(int n) {memset(table, -1, sizeof table);m.clear();bool status[20]; // 记录是否缺页int pageFaults = 0; // 缺页次数//clock_t start = clock(); // 获取开始时间// 获取开始时间auto start = high_resolution_clock::now();for (int j = 0; j < 20; j++) {int page = pages[j];if (!m.count(page)) { // 没命中就要加入或者替换页面if (m.size() >= n) {// 找到count最大的页面进行替换int maxpage = -1, maxcounts = -1;for (auto p : m) {if (p.second > maxcounts) {maxpage = p.first;maxcounts = p.second;}}m.erase(maxpage);}m[page] = 0;//没命中且主存没满则直接加入页面pageFaults++;status[j] = false; // 标记缺页}else {status[j] = true; // 标记命中m[page] = 0;}// 更新所有页面的count值:命中则置0,没命中加入新页面——满足条件则不加1即可,不管加不加入新页面,其他没中的页面都是要count+1的for (auto& p : m) {if (p.first != page) {p.second += 1;}}// 更新当前主存块内存在的页面int i = 0;for (auto p : m) {if (i < n) {//用一个i去便利贮存块,而不用fortable[i][j] = p.first;i++;}}//一开始写错了:/*for (int i = 0; i < n; i++) {for (auto p : m) {table[i][j] = p.first;}}*/}//clock_t end = clock(); // 获取结束时间// 获取结束时间auto stop = high_resolution_clock::now();auto duration = duration_cast<microseconds>(stop - start);// 输出结果表格cout << "主存块号 ";for (int j = 0; j < 20; j++) {cout << pages[j] << " ";}cout << endl;for (int i = 0; i < n; i++) {cout << "   " << i << "     ";for (int j = 0; j < 20; j++) {if (table[i][j] == -1) {cout << "  "; // 空块显示为空格}else {cout << table[i][j] << " ";}}cout << endl;}// 输出缺页标记cout << "是否缺页 ";for (int j = 0; j < 20; j++) {cout << (status[j] ? "\u221A " : "\u00D7 ");}cout << endl;cout << "LRU 缺页率: " << (float)(pageFaults) / 20 * 100 << "%" << endl;//cout << "运行时间: " << (double)(end - start) / CLOCKS_PER_SEC << " 秒" << endl;cout << "运行时间: " << duration.count() << " 微秒" << endl; // 输出运行时间
}int main() {cout << "内存容量为 3 块:\n";fifo(3);cout << endl;lru(3);cout << endl;cout << "内存容量为 4 块:\n";fifo(4);cout << endl;lru(4);return 0;
}

1)主存块数越多的,不论哪个算法,运行时间都更长一些,用的时chrono精确时间微妙

但是同样的,运行每次的时间不定

2)主存块数越多的,不论哪个算法,缺页率都更低一些


http://www.ppmy.cn/ops/136535.html

相关文章

linux下i2c开发与框架源码分析

目录 1 概述 2 I2c子系统框架 3 I2C的使用流程 3.1 在驱动里使用 3.2 在应用层使用 3.3 I2ctool的使用 4 为硬件i2c注册一个适配器 5 i2c子系统源码流程分析 5.1 i2c device与driver绑定过程 5.1.1 Driver的注册与处理 5.1.2 Client device的生成 5.2 I2c的发送与接…

【C++】类(三):类的其它特性

7.3 类的其它特性 本节将继续介绍之前章节当中 Sales_data 没有体现出来的类的特性&#xff0c;包括&#xff1a;类型成员、类的成员的类内初始值、可变数据成员、内联成员函数、从成员函数返回*this、如何定义并使用类类型及友元类等。 7.3.1 类成员再探 这部分定义了一对相…

机器学习入门-Scikit-learn

目录 一.Sklearn基本介绍 二.以鸢尾花数据集为例&#xff0c;理解基础运用 1.导入包 2.加载数据集 3.数据预处理 4.数据集拆分 5.模型训练 6.模型评估 7.模型保存和加载 三.碎碎念 一.Sklearn基本介绍 scikit-learn是一个开源的Python机器学习库&#xff0c;提供了大…

无Linux管理员权限,照样可以安装CUDA

以下演示内容使用CUDA版本为 CUDA11.7 1、官网 官网:CUDA官网下载地址 这里会列出所有的CUDA版本,选择需要的版本即可。 2、查看系统信息 这里分享三个命令,可以查看Linux系统的配置信息,方便下一步下载合适的CUDA版本。 可以根据这些命令输出的系统配置信息选择相应的…

阿里云IIS虚拟主机部署ssl证书

宝塔配置SSL证书用起来是很方便的&#xff0c;只需要在站点里就可以配置好&#xff0c;但是云虚拟主机在管理的时候是没有这个权限的&#xff0c;只提供了简单的域名管理等信息。 此处记录下阿里云&#xff08;原万网&#xff09;的IIS虚拟主机如何配置部署SSL证书。 进入虚拟…

IntelliJ IDEA常用快捷键

文章目录 环境快捷键外观编辑移动光标提示查找Live Templates列操作调试运行 环境 Ubuntu 24.04.1IntelliJ IDEA 2024.1.6 快捷键 外观 Alt 1&#xff1a;打开/关闭“项目”窗口&#xff08;即左边的导航窗口&#xff09; Alt 4&#xff1a;打开/关闭“运行”窗口 Alt …

HarmonyOS 应用中复杂业务场景下的接口设计

文章目录 前言设计理念与原则模块化设计动态可扩展性支持多种查询模式统一响应格式实现复杂业务接口示例后端接口代码&#xff08;Node.js Express&#xff09;前端调用代码&#xff08;ArkTS&#xff09;前端界面&#xff08;ArkUI&#xff09; 代码详解后端代码详解前端代码…

数据结构:链表进阶

链表进阶 1. ArrayList的缺陷2. 链表2.1 链表的概念及结构2.2 链表的实现 3.链表面试题4.LinkedList的使用5.1 什么是LinkedList4.2 LinkedList的使用 5. ArrayList和LinkedList的区别 1. ArrayList的缺陷 通过源码知道&#xff0c;ArrayList底层使用数组来存储元素&#xff1…