请求调页存储管理方式的模拟 含详细代码和实验结果截图

2023-10-28

请求调页存储管理方式的模拟

实验目的

通过对页面、页表、地址转换和页面置换过程的模拟,加深对请求调页系统的原理和实现过程的理解

实验内容
  1. 假设每个页面中可存放10条指令,分配给一作业的内存块数为4。
  2. 用C语言模拟一作业的执行过程。该作业共有320条指令,即它的地址空间为32页,目前它的所有页都还未调入内存。在模拟过程中,如果所访问的指令已经在内存中,则显示其物理地址,并转下一条指令。如果所访问的指令还未装入内存,则发生缺页,此时需记录缺页的次数,并将相应页调入内存。如果4个内存块中均已装入该作业,则需进行页面置换。最后显示其物理地址,并转下一条指令。在所有320条指令执行完毕后,请计算并显示作业运行过程中发生的缺页率。
  3. 置换算法:请分别考虑OPT、FIFO和LRU算法。
  4. 作业中指令的访问次序按下述原则生成:
    50%的指令是顺序执行的。
    25%的指令是均匀分布在前地址部分。
    25%的指令时均匀分布在后地址部分。
    具体的实施办法是:
    在[0,319]之间随机选取一条起始执行指令,其序号为m;
    顺序执行下一条指令,即序号为m+1的指令;
    通过随机数,跳转到前地址部分[0,m-1]中的某条指令处,其序号为m1;
    顺序执行下一条指令,即序号为m1+1的指令;
    通过随机数,跳转到后地址部分[m1+2,319]中的某条指令处,其序号为m2;
    顺序执行下一条指令,即序号为m2+1的指令;
    重复跳转到前地址部分、顺序执行、跳转到后地址部分、顺序执行的过程,直至执行320条指令。

1 当前需要执行的指令所在的页面在内存中则打印物理块编号来模拟真实物理地址的计算
2 不在内存中,但是内存中有空物理块则将页面直接调入内存,并打印物理块编号来模拟真实物理地址的计算
3 不在内存中,内存中也没有空物理块,则通过OPT、FIFO、LRU 三种置换算法来进行置换操作,置换完成后打印物理块编号来模拟真实物理地址的计算
4一些被注释的代码是作者调试时使用,读者可根据需要取消注释进行调试

源代码
// 当前需要执行的指令所在的页面在内存中则打印物理块编号来模拟真实物理地址的计算
// 不在内存中,但是内存中有空物理块则将页面直接调入内存,并打印物理块编号来模拟真实物理地址的计算
// 不在内存中,内存中也没有空物理块,则通过OPT、FIFO、LRU 三种置换算法来进行置换操作,置换完成后打印物理块编号来模拟真实物理地址的计算
// 一些被注释的代码是作者调试时使用,读者可根据需要取消注释进行调试 @Author-chenzhuo
#include <iostream>
#include<stdio.h>
#include <queue> //队列头文件
#include<time.h>
#define INSTR_NUM 320 // 指令条数
#define MEMORY_BLOCK_NUM 4 // 物理内存被划分的块数
#define INSTR_NUM_PER_PAGE 10 // 每个页面的指令条数
using namespace std;
typedef struct Block {
	int page_id;
	int next; // 在最佳替换算法中OPT使用,FIFO和LRU 均用队列来辅助实现
}Block;

int _index=0;
int instr[INSTR_NUM]; // 随机产生的指令执行序列数组
int lack_num; // 缺页次数,不同算法中将该值重置为0

Block memory_block[MEMORY_BLOCK_NUM]; // 内存物理块
// 返回某范围的随机数
int getRandom(int start, int end) {	
	int t = rand()%(end-start+1) + start;	
	int j;
	for (j=0; j<_index ;j++) {
		if (instr[j] == t) {
			break;
		}		
	}
	if (_index == j) {
		instr[_index++] = t;
	}	
	int k;
	for (k=0;k<_index;k++) {
		if (instr[k] == t+1) {
			break;
		}		
	}
	if (_index == k && t+1 < INSTR_NUM) {
		instr[_index++] = t+1;
	}
	return t;
}
// 初始化,给指令执行数组赋值
void init() {
	// 得到指令执行顺序,存入数组
	int t = getRandom(0, INSTR_NUM-1);
	while (_index<INSTR_NUM) {
		if(t==1 && _index == 2) {
			instr[_index++] = t-1;
		}
		if(t > 1) {
			int forword = getRandom(0, t-1);
		}
		if (t <= INSTR_NUM-3) {
			int last = getRandom(t+2, INSTR_NUM-1);
		}	
	}
	// 内存置空
	for (int i=0; i<MEMORY_BLOCK_NUM; i++) {
		memory_block[i].page_id = -1;
	}
	
}
// 当前页面是否已经调入页框
int isExistInMemory(int curr_page) {
	// 不存在内存中,返回-1 ,存在 返回所在物理块位置
	int is_exist = -1;
	for (int i=0; i<MEMORY_BLOCK_NUM; i++) {
		if (memory_block[i].page_id == curr_page) {
			is_exist = i;
			break;
		}
		
	}
	return is_exist;
}
// 是否有空闲页框
Block* findEmpty() {
	Block* empty = NULL;
	for (int i=0; i<MEMORY_BLOCK_NUM; i++) {
		if (memory_block[i].page_id == -1) {
			empty = & memory_block[i];
			break;
		}	
	}
	return empty;
}

// 在OPT中使用,找到应该被替换的页框
int findReplace() {
	int pos = 0;
	for(int i=0; i<MEMORY_BLOCK_NUM; i++) {
	   if(memory_block[i].next >memory_block[pos].next)
			pos = i;//找到应予置换页面,返回BLOCK中位置
	}
 return pos;
}


// 返回最佳被置换的页面
void findBeReplaceBlockByOPT(int index_) {
	for(int i=0; i<MEMORY_BLOCK_NUM; i++) {
		for(int j=index_+1; j<320; j++) {
			if(memory_block[i].page_id != instr[j]/INSTR_NUM_PER_PAGE){ 
				memory_block[i].next = 1000;          //最近此块并没有指令要被访问 
			} else { //将来不会用,设置为一个很大数
				memory_block[i].next = j;              //最近此块内要被访问的指令
				break;
			}
		}
	}
}

// 显示当前页的物理块(页框)编号,模拟真实物理地址的计算
void show(int curr_page) {
//	printf("物理地址分别是:\n");
	for (int i=0; i<MEMORY_BLOCK_NUM; i++) {
		if(memory_block[i].page_id == curr_page) {
//			printf("第%d页所在物理块编号:%d ", curr_page, i);
//			printf("物理地址:%d ", i);
			printf("%d ", i);
			break;
		}
	}
}
// 最佳页面替换算法
void OPT() {
	int pc;
	int curr_page;
	int is_exist;
	int position;
	lack_num = 0;
	Block* empty;
	printf("OPT:\n\n");
	for (int i=0; i<INSTR_NUM; i++) {
		pc = instr[i];
		// 指令是否在内存块中,在则打印,不在则调入
		curr_page = pc/INSTR_NUM_PER_PAGE; // 当前指令所在的页面编号
		is_exist = isExistInMemory(curr_page); // 当前页面是否在内存中 -1 表示不存在
		if(is_exist == -1) {
			lack_num++;
//			printf("第%d页不在内存\n", curr_page);
			// 内存是否还有剩余空间,有则直接调入,没有则根据OPT算法找到最合适的页面调出
			empty = findEmpty();
			if(empty != NULL) {
//				printf("将%d页调入内存\n",curr_page);
				empty -> page_id = curr_page;
			} else {
//				printf("将%d置换内存\n",curr_page);
				findBeReplaceBlockByOPT(i);
				position = findReplace();
				memory_block[position].page_id = curr_page;
			}
		}
		show(curr_page);		
	}
	printf("\n缺页率:%.2f %%\n",lack_num/320.0*100)	;	
}
// 最近最少使用页面替换算法
void LRU() {
	int pc;
	int curr_page;
	int is_exist;
	Block* empty;
	lack_num = 0;
	queue<int> queue_;
	printf("LRU:\n\n");
	for (int i=0; i<INSTR_NUM; i++) {
		queue<int> tempQueue;
		pc = instr[i];
		// 指令是否在内存块中,在则打印,不在则调入
		curr_page = pc/INSTR_NUM_PER_PAGE; // 当前指令所在的页面编号
		is_exist = isExistInMemory(curr_page); // 当前页面是否在内存中 -1 表示不存在
		if(is_exist == -1) {
			lack_num++;
//			printf("第%d页不在内存,缺页次数:%d\n", curr_page, lack_num);
			// 内存是否还有剩余空间,有则直接调入,没有则根据FIFO算法找到最合适的页面调出
			empty = findEmpty();
			if(empty != NULL) {
//				printf("将%d页调入内存\n",curr_page);
				empty -> page_id = curr_page;
				queue_.push(curr_page);
			} else {
				// 没有空块则置换
				int first = queue_.front();
//				printf("将%d页与内存中第%d页置换\n", curr_page, first);
				for(int j=0; j<MEMORY_BLOCK_NUM; j++) {
					if(memory_block[j].page_id == first) {
						memory_block[j].page_id = curr_page;
						break;
					}
					
				}
				queue_.pop();
				queue_.push(curr_page);	
			}
		} else {
			// 存在则放到栈顶
//			printf("将%d页放到栈顶\n", curr_page);
			int temp = -1;
			while (queue_.size() != 0) {
//				printf("当前队列大小:%lu\n", queue_.size());
				int first = queue_.front();
				if (first == curr_page ) {
					temp = first;
					queue_.pop();
				} else {
					tempQueue.push(first);
					queue_.pop();
				}
			}
			if (temp != -1) {
				tempQueue.push(temp);
			}
			
			queue_ = tempQueue;
		}
		show(curr_page);		
	}
	printf("\n缺页率:%.2f %%\n",lack_num/320.0*100)	;
}
// 先入先出页面替换算法
void FIFO() {
	int pc;
	int curr_page;
	int is_exist;
	Block* empty;
	lack_num = 0;
	queue<int> queue_;
	printf("FIFO:\n\n");
	printf("物理地址:\n");
	for (int i=0; i<INSTR_NUM; i++) {
		pc = instr[i];
		// 指令是否在内存块中,在则打印,不在则调入
		curr_page = pc/INSTR_NUM_PER_PAGE; // 当前指令所在的页面编号
		is_exist = isExistInMemory(curr_page); // 当前页面是否在内存中 -1 表示不存在
		if(is_exist == -1) {
			lack_num++;
//			printf("第%d页不在内存,缺页次数:%d\n", curr_page, lack_num);
			// 内存是否还有剩余空间,有则直接调入,没有则根据FIFO算法找到最合适的页面调出
			empty = findEmpty();
			if(empty != NULL) {
//				printf("将%d页调入内存\n",curr_page);
				empty -> page_id = curr_page;
				queue_.push(curr_page);
			} else {
				int first = queue_.front();
//				printf("将%d页与内存中第%d页置换\n", curr_page, first);
				for(int j=0; j<MEMORY_BLOCK_NUM; j++) {
					if(memory_block[j].page_id == first) {
						memory_block[j].page_id = curr_page;
						break;
					}				
				}
				queue_.pop();
				queue_.push(curr_page);
				
			}
		}
		show(curr_page);		
	}	
	printf("\n缺页率:%.2f %%\n",lack_num/320.0*100)	;	
}
int main(){
	// 以时间作为随机数种子
	srand((unsigned)time(NULL));
	init();
	printf("\n随机产生的指令执行序号:\n");
	for(int i=0;i<INSTR_NUM;i++) {
		printf("%d ", instr[i]);
	}
	printf("\n\n");
	// 每次只能使用一种算法
//	OPT();
//	FIFO();
	LRU();
	return 0;
}


实验结果(示例)

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

请求调页存储管理方式的模拟 含详细代码和实验结果截图 的相关文章

  • 将复选框添加到 UniformGrid

    我正在尝试将复选框动态添加到 wpf 中的统一网格中 但看起来网格没有为它们分配足够的空间 所以它们都有点互相重叠 这就是我将它们添加到后面的代码中的方法 foreach string folder in subfolders PathCh
  • C++ 子字符串返回错误结果

    我有这个字符串 std string date 20121020 我正在做 std cout lt lt Date lt lt date lt lt n std cout lt lt Year lt lt date substr 0 4 l
  • 使闭包捕获的变量变得易失性

    闭包捕获的变量如何与不同线程交互 在下面的示例代码中 我想将totalEvents 声明为易失性的 但C 不允许这样做 是的 我知道这是错误的代码 这只是一个例子 private void WaitFor10Events volatile
  • 当 contains() 工作正常时,xpath 函数ends-with() 工作时出现问题

    我正在尝试获取具有以特定 id 结尾的属性的标签 like span 我想获取 id 以 国家 地区 结尾的跨度我尝试以下xpath span ends with id Country 但我得到以下异常 需要命名空间管理器或 XsltCon
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 在 Visual Studio 2008 上设置预调试事件

    我想在 Visual Studio 中开始调试程序之前运行一个任务 我每次调试程序时都需要运行此任务 因此构建后事件还不够好 我查看了设置的 调试 选项卡 但没有这样的选项 有什么办法可以做到这一点吗 你唯一可以尝试的 IMO 就是尝试Co
  • C - 找到极限之间的所有友好数字

    首先是定义 一对友好的数字由两个不同的整数组成 其中 第一个整数的除数之和等于第二个整数 并且 第二个整数的除数之和等于第一个整数 完美数是等于其自身约数之和的数 我想做的是制作一个程序 询问用户一个下限和一个上限 然后向他 她提供这两个限
  • 获取没有非标准端口的原始 url (C#)

    第一个问题 环境 MVC C AppHarbor Problem 我正在调用 openid 提供商 并根据域生成绝对回调 url 在我的本地机器上 如果我点击的话 效果很好http localhost 12345 login Request
  • 在 ASP.NET Core 3.1 中使用包含“System.Web.HttpContext”的旧项目

    我们有一些用 Net Framework编写的遗留项目 应该由由ASP NET Core3 1编写的API项目使用 问题是这些遗留项目正在使用 System Web HttpContext 您知道它不再存在于 net core 中 现在我们
  • 将自定义元数据添加到 jpeg 文件

    我正在开发一个图像处理项目 C 我需要在处理完成后将自定义元数据写入 jpeg 文件 我怎样才能做到这一点 有没有可用的图书馆可以做到这一点 如果您正在谈论 EXIF 元数据 您可能需要查看exiv2 http www exiv2 org
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • 当操作繁忙时,表单不执行任何操作(冻结)

    我有一个使用 C 的 WinForms 应用程序 我尝试从文件中读取一些数据并将其插入数据表中 当此操作很忙时 我的表单冻结并且无法移动它 有谁知道我该如何解决这个问题 这可能是因为您在 UI 线程上执行了操作 将文件和数据库操作移至另一个
  • 将 xml 反序列化为类,list<> 出现问题

    我有以下 XML
  • 如何让Gtk+窗口背景透明?

    我想让 Gtk 窗口的背景透明 以便只有窗口中的小部件可见 我找到了一些教程 http mikehearn wordpress com 2006 03 26 gtk windows with alpha channels https web
  • 32 位到 64 位内联汇编移植

    我有一段 C 代码 在 GNU Linux 环境下用 g 编译 它加载一个函数指针 它如何执行并不重要 使用一些内联汇编将一些参数推送到堆栈上 然后调用该函数 代码如下 unsigned long stack 1 23 33 43 save
  • 为什么我收到“找不到编译动态表达式所需的一种或多种类型。”?

    我有一个已更新的项目 NET 3 5 MVC v2 到 NET 4 0 MVC v3 当我尝试使用或设置时编译出现错误 ViewBag Title财产 找不到编译动态表达式所需的一种或多种类型 您是否缺少对 Microsoft CSharp
  • 如何在 C++ BOOST 中像图形一样加载 TIFF 图像

    我想要加载一个 tiff 图像 带有带有浮点值的像素的 GEOTIFF 例如 boost C 中的图形 我是 C 的新手 我的目标是使用从源 A 到目标 B 的双向 Dijkstra 来获得更高的性能 Boost GIL load tiif
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我
  • 恢复上传文件控制

    我确实阅读了以下帖子 C 暂停 恢复上传 https stackoverflow com questions 1048330 pause resume upload in c 使用 HTTP 恢复上传 https stackoverflow

随机推荐

  • 【笔记】Nginx+Ngrok实现80端口服务器+80端口内网穿透

    安装ngrok 笔记 ngrok安装方法 安装完毕后ngrok默认将服务器的80端口占用 这时 需要修改启动脚本 vim etc init d ngrokd 找到如下部分 nohup sudo bin ngrokd tlsKey serve
  • 【每日一题】-金牌榜排序

    文章目录 题目描述 输入 输出 样例 解析 代码 题目描述 2012伦敦奥运会即将到来 大家都非常关注奖牌榜的情况 现在我们假设奖牌榜的排名规则如下 1 首先gold medal 数量多的排在前面 2 其次silver medal 数量多的
  • SpringBoot中 Lua函数操作redis

    Lua Lua 是一个简洁 轻量 可扩展的脚本语言 它的特性有 轻量 源码包只有核心库 编译后体积很小 高效 由 ANSI C 写的 启动快 运行快 内嵌 可内嵌到各种编程语言或系统中运行 提升静态语言的灵活性 如 OpenResty 就是
  • xman的思维导图快捷键_这个良心好用的思维导图软件,居然不用氪金充钱

    今天给大家介绍一款免费的在线思维导图工具 GitMind 提供了丰富的功能和模板 可免费导出 JPG PNG 图片 PDF 文档以及 TXT 文本等多种格式 此外 GitMind 还集成了制作流程图的能力 网站展示的流程图示例有泳道图 拓扑
  • Springboot项目使用达梦数据库

    下载达梦数据库驱动 Dm7JdbcDriver16 jar 执行maven命令把驱动包打入本地maven仓库 mvn install install file DgroupId com dm DartifactId DmJdbcDriver
  • 学校计算机如何脱控,学校机房脱控方法(已控状态)/极域电子教室脱离老师控制图文教程...

    老师没控制的时候 刀友应该都会断掉控制吧 我就不说了 就说说老师老师已经控制了该如何脱离控制 拔网线比较麻烦就不说了 以下操作之前先检查极域电子教室 右键右下角极域电子教室端 打开设置 把禁止结束学生端进程前面的勾去掉 把断网锁屏前面的勾去
  • 部署ELFK

    目录 ELFK ES logstash filebeat kibana 环境准备 所有节点 Elasticsearch 集群部署 在Node1 Node2节点上操作 修改elasticsearch主配置文件 es 性能调优参数 启动elas
  • Marriage is Stable

    http acm hdu edu cn showproblem php pid 1522 Problem Description Albert Brad Chuck are happy bachelors who are in love w
  • JVM--三大子系统详解

    首先需要了解java的命令 javac 将java文件编译为 class文件 里面是一些二进制文件 javap c 将 class文件变为反汇编 例如 javap c hello class gt demo txt 可以将class文件转化
  • GPIO介绍

    目录 一 GPIO是什么 二 STM32引脚分类 三 GPIO内部结构 四 GPIO的工作模式 4 1 输入模式 模拟 上拉 下拉 浮空 4 2 输出模式 推挽 开漏 4 3 复用功能 推挽 开漏 4 4 模拟输入输出 上下拉无影响 一 G
  • c语言将csv文件存储到数组,读取CSV文件并将值存储到数组中

    青春有我 我最喜欢的CSV解析器是一个内置在 NET库中的解析器 这是Microsoft VisualBasic命名空间中隐藏的宝藏 下面是一个示例代码 using Microsoft VisualBasic FileIO var path
  • ConcurrentHashMap 的实现原理

    目录 常见问题 1 concurrentHashMap特点 2 concurrentHashMap如何保证效率高 又安全的 1 构造函数 2 put方法 2 1 initTable 2 2 addCount方法 3 get方法 常见问题 1
  • 【SpinalHDL】Windows10系统搭建SpinalHDL 开发环境

    本文主要记载如何从零开始在win平台搭建SpinalHDL开发环境并跑通第一个spinal project demo 1 环境准备 1 1 软件下载 首先列出需要安装的软件 并逐一对这些软件的功能和其必要性进行说明 需要安装的软件 IDEA
  • 继电器的过流过压保护(自恢复保险丝)

    简述 继电器广泛应用于消费电子产业和工业设备中 它具有控制系统 又称输入回路 和被控制系统 又称输出回路 它实际上是用较小的电流去控制较大电流的一种 自动开关 故在电路中起着自动调节 安全保护 转换电路等作用 继电器可能因为过流或者过压而损
  • arduino/mixly TFT显示SD卡的图片

    一 器材 SD卡模块 1 8寸TFT屏 ST7735 arduino uno开发板 SD卡 二 接线 TFT屏 arduino uno GND GND VCC 5V SCL D13 SDA D11 RES D8 DC D10 CS D9 B
  • Java锁机制

    Java锁主要是为了解决线程安全问题 当多个线程共享同一个变量时可能会出现同时修改变量的情况 这样会导致最终计算结果错误 未解决该问题 Java提供了各种锁来确保数据能够被正常修改和访问 最常用的比如synchronized 一 互斥同步
  • python计算机视觉学习第三章——图像到图像的映射

    目录 引言 一 单应性变换 1 1 直接线性变换算法 1 2 仿射变换 二 图像扭曲 2 1 图像中的图像 2 2 分段仿射扭曲 2 2 图像配准 三 创建全景图 3 1 RANSAC 随机一致性采样 3 2 拼接图像 四 总结 引言 本章
  • [4G&5G专题-119]:5G培训应用篇-4-5G典型行业应用的解决方案(车联网、智慧医疗、智能教育、智能电网)

    目录 前言 前言 1 总目录 前言 2 本章 第1章 5G行业应用介绍 第2章 车联网解决方案 2 1 车联网概述 2 2 车联网需求分析 2 3 车联网解决方案 第3章 智慧医疗解决方案 第4章 智能教育解决方案 第5章 智能电网解决方案
  • Mybatis配置多数据源

    前言 Spring Boot项目使用Mybatis 既要从上游系统同步数据 又要操作本系统的数据库 所以需要引入双数据源 配置Mybatis 步骤 一 配置双数据源 连接数据库 1 禁用Spring Boot数据源的自动装配 在启动类 Sp
  • 请求调页存储管理方式的模拟 含详细代码和实验结果截图

    请求调页存储管理方式的模拟 实验目的 通过对页面 页表 地址转换和页面置换过程的模拟 加深对请求调页系统的原理和实现过程的理解 实验内容 假设每个页面中可存放10条指令 分配给一作业的内存块数为4 用C语言模拟一作业的执行过程 该作业共有3