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

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(使用前将#替换为@)

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

  • 如何使用 C# 中的参数将用户重定向到 paypal

    如果我有像下面这样的简单表格 我可以用它来将用户重定向到 PayPal 以完成付款
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 如何使用 ICU 解析汉字数字字符?

    我正在编写一个使用 ICU 来解析由汉字数字字符组成的 Unicode 字符串的函数 并希望返回该字符串的整数值 五 gt 5 三十一 gt 31 五千九百七十二 gt 5972 我将区域设置设置为 Locale getJapan 并使用
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur

随机推荐

  • 【笔记】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