操作系统:用C语言模拟先进先出的算法(FIFO)、最久未使用算法(LRU)、改进的Clock置换算法的命中率。

news2025/2/25 9:43:08

2.1 实验目的

  通过请求页面式存储管理中页面置换算法设计,了解存储技术的特点,掌握请求页式存储管理的页面置换算法。

2.2 实验内容

用程序实现生产者——消费者问题,将指令序列转换为用户虚存中的请求调用页面流。

具体要求:

  1. l页面大小为1K
  1. l用户内存容量为4页到40页
  1. l用户外存的容量为40k

在用户外存中,按每K存放10条指令,400条指令在外存中的存放方式为:

  1. l0-9条指令为第0页
  1. l10-19条指令为第1页

。。。。。

  1. l390-399条指令为第39页

按以上方式,用户指令可组成40页,通过随机数产生一个指令序列,共400个指令(0-399)。模拟请求页式存储管理中页面置换算法,执行一条指令,首先在外存中查找所对应的页面和页面号,然后将此页面调入内存中,模拟并计算下列三种算法在不同内存容量下的命中率(页面有效次数/页面流的个数):

1.先进先出的算法(FIFO)

2.最久未使用算法(LRU)

3.改进的Clock置换算法

提示

·随机指令的产生 :rand() 或srand()

·用户内存中页面控制结构采用链表

struct p_str{

int pagenum; /* 页号 */

int count; /* 访问页面的次数 */

struct p_str next; /* 下一指针 */

}p_str;

2.3算法描述

FIFO先入先出算法采用队列思想,先调入内存的页放在最前面,当内存存满时新的不同的页需要调入内存时,旧的页要进行依次出队,然后将新的页放入队列最后。

LRU最久未使用算法在使用时增加了一个时间time参数,当一个内存的页刚被调入或者访问时,time会归零,当在一次时间片内未使用时时间参数time++。当内存存满且有新的页调入内存时时,会在内存中挑选time最大的页进行删除,并将新的页填入。

改进Clock置换算法一共分四步,当内存存满且有新页调入时,先寻找A=0且M=0的进行替换,如果没有则寻找A=0且M=1进行替换,如果没有将所有内存中的页的A便为0,在重复以上两步进行内存中的新旧页替换。

2.4 实验结果(Linux虚拟机运行)

编译指令:g++ -o page page.cpp

运行指令:./page

根据数学计算可知,当内存页为40时,三种算法的命中率均为90及以上。

当内存页小于40时,三种算法在随机生成页时命中率是离散的

2.5 小结

本代码中FIFO采用队列并没有太大难度,而LRU相对FIFO仅是增加了一个时间变量用来选择置换的页,也就是说每次置换相对于FIFO要多出一个遍历求最大值的过程,也不能忘了在对链表进行增删的时候应该在遍历时遍历到length-1以此到达要删除结点的前一个结点,这样直接令前一结点的next=next->next,十分方便。代码中最难的就是改进Clock算法,其难就难在于多次进行链表遍历和增删所导致的结点为NULL或者爆内存的情况,因此最应该注意的是一共需要每次增删最多会遍历四次,所以在引用游标指针pp时应该在每次遍历完的时候重新让其等于begin也就是队首,这样才能保证代码不报错或者得出的测试概率错误。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#define maxsize 400	/*400访问次数*/
typedef struct p_str {
	int pagenum; /* 页号 */
	int count; /* 访问页面的次数 */
	int aa;/*访问位(Clock)*/
	int mm;/*修改位(Clock)*/
	int longtime;/*未使用的时间(LRU)*/
	struct p_str* next; /* 下一指针 */
}p_str;
int n;
void FIFO();
void LRU();
void Improve_Clock();

int main() {
	int m;
	srand((unsigned)time(NULL));
	scanf("%d %d", &n, &m); //输入内存容量和测试次数
	int i = m;
	while (m--) {
		printf("\n第%d次测试\n", i - m);
		//cout << endl << "第" << i - m << "次测试" << endl;
		FIFO();
		LRU();
		Improve_Clock();
	}
}

void FIFO() {
	double effective = 0;	/*有效访问次数*/
	int length = 0;		/*队列长度*/
	p_str* begin = (p_str*)malloc(sizeof(p_str));		/*创建头结点*/
	p_str* end = begin;		/*创建尾结点*/
	begin->count = -1; begin->pagenum = -1; begin->next = NULL;
	for (int i = 0; i < maxsize; i++) {	/*400次随机数测试*/
		int t = 0;
		int page = rand() % 400 / 10;
		p_str* pp = begin;
		for (int j = 0; j < length; j++) {		/*先遍历看内存是否有相同的页*/
			pp = pp->next;
			if (pp->pagenum == page) {		/*有则有效次数加一*/
				pp->count++;
				t = 1;
				effective++;
				break;
			}
		}
		if (t == 0) {		/*进行无效访问,即添加结点或替换节点*/
			if (length < n) {		/*内存未满,添加结点*/
				p_str* q = (p_str*)malloc(sizeof(p_str));
				q->count = 1; q->pagenum = page; q->next = NULL;
				end->next = q;
				end = q;
				length++;
			}
			else {		/*内存已满,删除表头结点,新结点加到表尾*/
				begin->next = begin->next->next;
				p_str* q = (p_str*)malloc(sizeof(p_str));
				q->count = 1; q->pagenum = page; q->next = NULL;
				end->next = q;
				end = q;
			}
		}
	}
	printf("在页面流个数为%d,内存容量为%d页的条件下,FIFO命中率为:%f %%\n", maxsize, n, (effective / 400) * 100);
	//cout << "在页面流个数为" << maxsize << ",内存容量为" << n << "页的情况下,FIFO命中率为:" << (effective / 400) * 100 << "%" << endl;
}

void LRU() {
	double effective = 0;	/*有效访问次数*/
	int length = 0;		/*队列长度*/
	p_str* begin = (p_str*)malloc(sizeof(p_str));	/*创建头尾结点*/
	p_str* end = begin;
	begin->count = -1; begin->pagenum = -1; begin->longtime = -1; begin->next = NULL;
	for (int i = 0; i < maxsize; i++) {		/*400次随机数测试*/
		int t = 0;
		int page = rand() % 400 / 10;
		p_str* pp = begin;
		for (int j = 0; j < length; j++) {		/*遍历内存看是否可以有效访问*/
			pp = pp->next;
			if (pp->pagenum == page) {
				pp->count++; pp->longtime = -1; t++; effective++; break;
			}
		}
		if (!t) {		/*无效访问*/
			if (length < n) {		/*添加结点*/
				p_str* q = (p_str*)malloc(sizeof(p_str));
				q->count = 1; q->pagenum = page; q->next = NULL; q->longtime = -1;
				end->next = q;
				end = q;
				length++;
			}
			else {
				int max, maxtime = -1;		/*最久未访问结点位置,最久未访问时间*/
				pp = begin;
				for (int j = 0; j < length; j++) {		/*寻找最久未访问的结点*/
					pp = pp->next;
					if (pp->longtime > maxtime) {
						maxtime = pp->longtime;
						max = j;
					}
				}
				pp = begin;
				for (int j = 0; j < max - 1; j++) {		/*删除该结点*/
					pp = pp->next;
				}
				pp->next = pp->next->next;
				p_str* q = (p_str*)malloc(sizeof(p_str));	/*添加新结点*/
				q->count = 1; q->pagenum = page; q->next = NULL; q->longtime = -1;
				end->next = q;
				end = q;
			}
		}
		pp = begin;
		for (int j = 0; j < length; j++) {		/*所有未被访问节点时间加一*/
			pp = pp->next;
			pp->longtime++;
		}
	}
	printf("在页面流个数为%d,内存容量为%d页的条件下,LRU命中率为:%f %%\n", maxsize, n, (effective / 400) * 100);
	//cout << "在页面流个数为" << maxsize << ",内存容量为" << n << "页的情况下,LRU命中率为:" << (effective / maxsize) * 100 << "%" << endl;
}

void  Improve_Clock() {
	double effective = 0;	/*有效访问次数*/
	int length = 0;		/*队列长度*/
	p_str* begin = (p_str*)malloc(sizeof(p_str));		/*创建头尾结点*/
	p_str* end = begin;
	begin->count = -1; begin->pagenum = -1; begin->aa = -1; begin->mm = -1; begin->next = NULL;
	for (int i = 0; i < maxsize; i++) {
		int t = 0;
		int page = rand() % 400 / 10;
		int  m = rand() % 2;
		p_str* pp = begin;
		for (int j = 0; j < length; j++) {		/*尝试有效访问*/
			pp = pp->next;
			if (pp == NULL) {
				pp = end;
			}
			if (pp->pagenum == page) {
				pp->aa = 1; t++; effective++; break;
			}
		}
		if (!t) {
			if (length < n) {		/*添加结点*/
				p_str* q = (p_str*)malloc(sizeof(p_str));
				q->count = 1; q->pagenum = page; q->next = NULL; q->longtime = -1; q->aa = 1; q->mm = m;
				end->next = q;
				end = q;
				length++;
			}
			else {
				int f = 0;
				p_str* q = (p_str*)malloc(sizeof(p_str));
				q->count = 1; q->pagenum = page; q->next = NULL; q->longtime = -1; q->aa = 1; q->mm = m;
				p_str* pp = begin;
				for (int j = 0; j < length-1; j++) {
					if (pp->next->aa == 0 && pp->next->mm == 0) {		/*寻找A=0,M=0替换*/
						pp->next = pp->next->next;
						end->next = q;
						end = q;
						f = 1; break;
					}
					else {
						pp = pp->next;
					}
				}
				if (f)continue;
				else {
					pp = begin;
					for (int j = 0; j < length-1; j++) {
						if (pp->next->aa == 0 && pp->next->mm == 1) {		/*寻找A=0,M=1替换*/
							pp->next = pp->next->next;
							end->next = q;
							end = q;
							f = 1; break;
						}
						else {
							pp = pp->next;
						}
					}
				}
				if (f)continue;
				else {
					pp = begin;
					for (int j = 0; j < length; j++) {		/*所有结点A归零*/
						pp = pp->next;
						pp->aa = 0;
					}
				}
				pp = begin;
				for (int j = 0; j < length-1; j++) {
					if (pp->next->aa == 0 && pp->next->mm == 0) {	/*寻找A=0,M=0替换*/
						pp->next = pp->next->next;
						end->next = q;
						end = q;
						f = 1; break;
					}
					else {
						pp = pp->next;
					}
				}
				if (f)continue;
				else {
					pp = begin;
					for (int j = 0; j < length-1; j++) {
						if (pp->next->aa == 0 && pp->next->mm == 1) {	/*寻找A=0,M=1替换*/
							pp->next = pp->next->next;
							end->next = q;
							end = q;
							f = 1; break;
						}
						else {
							pp = pp->next;
						}
					}
				}
			}
		}
	}
	//cout << "在页面流个数为" << maxsize << ",内存容量为" << n << "页的情况下,优化Clock命中率为:" << (effective / maxsize) * 100 << "%" << endl;
	printf("在页面流个数为%d,内存容量为%d页的条件下,优化Clock命中率为:%f %%\n", maxsize, n, (effective / 400) * 100);
}

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

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

相关文章

以太坊的ecrecover预编译合约

1. 引言 前序博客&#xff1a; ECDSA VS Schnorr signature VS BLS signature ECDSA&#xff0c;全称为Elliptic curve Digital Signature Algorithm&#xff0c;采用Elliptic curve cryptography来实现的数字签名算法。 公私钥对(pk,P)(pk,P)(pk,P)&#xff0c;其中公钥Pp…

阿里云-数据仓库-全链路大数据开发治理平台-DataWorks的数字世界

一、前言 上文我讲到 阿里云-数据仓库-数据分析开发神器-ODPS &#xff0c;今天我带领大家一起走进神器的成长环境及它的数据世界。 二、 DataWorks是什么 DataWorks基于MaxCompute、Hologres、EMR、AnalyticDB、CDP等大数据引擎&#xff0c;为数据仓库、数据湖、湖仓一体等…

大数据-压缩与打包

一、gzip命令 1、选项参数 参数作用-c&#xff08;compress&#xff09;将压缩的数据输出到标准输出&#xff08;stdout&#xff09;上-d&#xff08;decompress&#xff09;解压缩-t&#xff08;test&#xff09;可以用来检验一个压缩文件的一致性&#xff0c;看看文件有无错…

艾美捷甘油比色测定试剂盒-简单,敏感,高效

艾美捷甘油比色测定试剂盒&#xff0c;利用双酶联反应系统来检测血清和血浆中的甘油的含量.最后用酶标仪在540nm处测吸光度值即可. 甘油是甘油三酯的骨架&#xff0c;是参与氧化和合成过程的能量代谢的重要中间体。甘油和游离脂肪酸循环水平的测量被认为反映了脂肪分解&#xf…

快应用的优势与劣势对比

2018年&#xff0c;“快应用”标准正式推出。快应用是九大手机厂商基于硬件平台共同推出的新型应用生态。用户无需下载安装&#xff0c;即点即用&#xff0c;享受原生应用的性能体验。 快应用框架深度集成进各厂商手机系统中&#xff0c;可以在操作系统层面实现用户需求与应用…

艾美捷甘油比色测定试剂盒基本参数和相关文献说明

背景&#xff1a; 哺乳动物中&#xff0c;甘油三脂主要储存在脂肪组织中&#xff0c;作为主要的能量储存仓库.当禁食阶段&#xff0c;存储在肝脏和脂肪组织中的甘油三酯被脂肪酶分解形成脂肪酸和甘油. 艾美捷甘油比色测定试剂盒基本参数&#xff1a; 中文名称&#xff1a;甘油…

dpdk中的librte_malloc库

dpdk中的librte_malloc库提供了能够分配任意大小内存的API。 该库的目标是提供类似malloc的函数从hugepage中分配内存&#xff0c;以及帮助应用程序移植。 通常情况下&#xff0c;这种类型的分配不应该在数据平面处理&#xff0c;因为其比基于内存池的分配更慢&#xff0c; …

网站被反诈中心DNS劫持解决教程

如果你的网站部分地区用户访问反馈访问不了&#xff0c;测试域名DNS被劫持到了127.0.0.1 或 0.0.0.0 可能是域名被墙了&#xff0c;或则被反诈中心拦截了&#xff0c;如果遇到该问题&#xff0c;需要检测单单被运营商拦截还是也有被反诈中心拦截。 排查过程: 可以把问题域名通过…

H5 雪碧图 移动的机器猫

精灵图&#xff08;英语&#xff1a;Sprite&#xff09;&#xff0c;又被称为雪碧图或拼合图。在计算机图形学中&#xff0c;当一张二维图像 集成进场景中&#xff0c;成为整个显示图像的一部分时&#xff0c;这张图就称为精灵图。 本文中用的就是这张&#xff0c;来自爱给网。…

Python:Flask简介与实践

文章目录简介一、简单使用二、调试模式三、路由四、路径变量五、构造URL六、HTTP方法七、静态文件八、模板生成九、日志输出十、处理请求1. Request 对象十一、文件上传十二、Cookies十三、重定向和错误十四、响应处理十五、Sessions十六、模板简介1. 模板标签2. 继承3. 控制流…

超高精度PID控制器的特殊功能(2)——远程操作软件及其安装使用

摘要&#xff1a;远程控制软件是高级PID调节器随机配备的一种计算机软件&#xff0c;可在计算机上远程进行调节器的所有操作&#xff0c;并还具有过程曲线显示和存储功能。本文主要针对VPC 2021系列超高精度PID控制器&#xff0c;介绍了随机配备的控制软件的安装和一些最基本的…

2022-12-21 Buildroot创建自己的软件包,把一个c应用编译到系统里面去运行

一、Buildroot 编译完成后&#xff0c;会在 /buildroot/output/xxxx/host/ 目录下&#xff0c;生成交叉编译工具&#xff0c;我们可以用来编译目标程序。 1、比如我现在要编译下面的c文件 #include <stdio.h> #include <stdlib.h> int main(int argc,char *argv[…

分布式是大数据处理的万能药?

前言&#xff1a;分布式是大数据处理的万能药&#xff1f;今天叶秋学长跟大家一起探讨这个问题~ 使用分布式集群来处理大数据是当前的主流&#xff0c;将一个大任务拆分成多个子任务分布到多个节点进行处理通常能获得显著的性能提升。因此&#xff0c;只要发现处理能力不足就可…

人数超员识别系统 yolov5

人数超员识别系统基于计算机视觉分析技术yolov5网络架构对现场画面实时分析&#xff0c;如监测到区域超员时&#xff0c;立刻抓拍存档并告警提示。YOLOv5是一种单阶段目标检测算法&#xff0c;该算法在YOLOv4的基础上添加了一些新的改进思路&#xff0c;使其速度与精度都得到了…

Java日志技术是什么

文章目录日志技术日志技术介绍日志技术体系日志技术 日志技术介绍 想清楚的知道一个系统运行的过程和详情就需要日志记录 日志介绍: 生活中的日志&#xff1a; 生活中的日志就好比日记&#xff0c;可以记录你生活的点点滴滴。 程序中的日志&#xff1a; 程序中的日志可以用来记…

04---springboot实现增删改查

1、配置文件 application.yml server:port: 8081 spring:mvc:path match:matching-strategy: ant_path_matcherdatasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: 123456url: jdbc:mysql://localhost:3306/management?useUnicodetrue&use…

C++ STL 之关联容器 map 详解

文章目录Part.I AttentionChap.I 注意事项Chap.II 操作技巧Part.II FuncitonPart.III CodeChap.I mapChap.II unordered_mapChap.III multimapPart.I Attention C 中 map 提供的是一种键值对容器&#xff0c;里面的数据都是成对出现的&#xff0c;每一对中的第一个值称之为关键…

博苑股份冲刺创业板上市:上半年净利润约1亿元,李成林为董事长

近日&#xff0c;山东博苑医药化学股份有限公司&#xff08;下称“博苑股份”或“博苑医药”&#xff09;在深圳证券交易所创业板更新招股书。据贝多财经了解&#xff0c;博苑股份于2022年6月17日递交招股书&#xff0c;准备在创业板上市。 本次冲刺创业板上市&#xff0c;博苑…

服务的消费方式和服务熔断

目录 1. 服务消费方式 1.1 RestTemplate 1.2 feign 2. 服务熔断&#xff08;降级&#xff09; 2.1 在微服务架构中服务熔断的必要性 健康的微服务集群&#xff1a; ​编辑 出现故障&#xff1a; ​编辑 系统雪崩&#xff1a; ​编辑 2.2 hystrix 2.3 hystrix的使用…

[Linux]多线程的同步和互斥(线程安全 | 互斥锁 | 死锁 | 条件变量)

文章目录Linux线程互斥进程线程间的互斥相关背景概念互斥量mutex互斥量的接口初始化互斥量销毁互斥量互斥量的加锁和解锁互斥量实现原理可重入vs线程安全常见线程不安全情况常见线程安全的情况常见不可重入的情况常见可重入的情况可重入与线程安全的联系可重入与线程安全的区别…