操作系统_动态页式存储管理的模拟实现_附源码运行截图_C++

实现提示:

1最近没有使用页面淘汰算法NUR

(1)原理简述:

所谓“最近未使用”首先是要对“近”作一个界定,比如CLEAR_PERIOD=50,便是在CPU最近的50次进程页面处理工作中,找出这50次都没有处理到的页面;如果

⑴ 这样的页面只有一个,就将其换出,放入需处理的新页面;

⑵ 有不只一个这样的页面,在这些页面中任取一个换出(可以是下标最小的,或者下标最大的,都随便),放入需处理的页面;

⑶ 没有一个这样的页面,随意换出一个页面(可以是下标最小的,或者下标最大的,都随便)。

算法特点:有一个循环周期,每到达这个周期,所有页面存放是否被CPU处理信息的属性均被置于初始态(没有被访问)。

(2)图表描述:

还用前面的例子,某进程在硬盘上被划为5个页面,用1、2、3、4、5表示,而处理机处理它们的顺序为:

1、4、2、5、3、3、2、4、2、5

而内存可以控制的页面数为3(AP=3),CLEAR_PERIOD取5;循环周期内,如果所有内存页面均被CPU处理或有多个页面未被CPU处理,取页码最小的页面换出。

 

2理想型淘汰算法OPT

(1)原理简述:

前提还是在分配的内存页面占满的情况下。所谓的最佳置换法是一种理想状况下的算法,它要求先遍历所有的CPU待处理的进程页面序列(实际上由于待处理的页面有时取决于先前处理的页面,所有很多情况下不可能得到完整的待处理页面序列。在这个层面上,才说该算法是理想的。),在这些页面中,如果有已经在内存当中,而CPU不再处理的,就将其换出;如果页面在内存中,并且CPU待处理,就取从当前位置算起,最后处理到的页面,将其换出,比如CPU待处理的页面序列号为:

1

3

2

2

4

5

2

5

1

4

3

4

1

1

5

5

3

4

2

1

已经处理了5个页面(底纹为灰色),那么页面5是第一个待处理的页面;2是第二个;1是第四个;4是第五个;3是第六个。那么页面3就是针对当前位置而言,最后处理到的页面。

(2)图表描述:

还用前面的例子,某进程在硬盘上被划为5个页面,用1、2、3、4、5表示,而处理机处理它们的顺序为:

1、4、2、5、3、3、2、4、2、5

而内存可以控制的页面数为3(AP=3),


 代码实现:

//Lz毅

#include<iostream>
#include<string>
using namespace std;

#define M 10 //内存页最大长度
#define N 50 //处理的页面最大长度

typedef struct page
{
	int name = 0;//存放的页号
	//近期没有使用作为判断是否处理到0为未处理,1为处理
	//最佳置换 从当前位置到需要处理的位置的距离 换出大的
	int num = 0;
};
page pagelist[M];//内存页
int handle[N];//处理机处理的页面的顺序
int len;//handle页面的长度
int AP;//总页面数
int outputlist[M][N];//与算法无关方便查看 输出显示 按列存储 按行显示

void write(int i)//将显示结果保存 方便显示
{
	for (int j = 0; j < AP; j++)
	{
		outputlist[j][i] = pagelist[j].name;
	}
}

void NUR(int CLEAR_PERIOD)//最近没有使用页面淘汰算法
{
	int i, j;
	for (i = 0; i < AP; i++)//先把页面填满再开始替换
	{
		pagelist[i].name = handle[i];
		pagelist[i].num = 1;
		write(i);
	}
	for (; i < len; i++)//填满之后开始
	{
		if (i % CLEAR_PERIOD == 0)//每过一定时间标志就清零
		{
			for (j = 0; j < AP; j++)//清零
			{
				pagelist[j].num = 0;
			}
		}
		for (j = 0; j < AP; j++)//查找页面是否已经在内存
		{
			if (pagelist[j].name == handle[i])
			{
				pagelist[j].num = 1;
				break;
			}
		}
		if (j == AP)//遍历完也没有找到 缺页
		{
			for (j = 0; j < AP; j++)//从头向后 找第一个周期内没访问的 
			{
				if (pagelist[j].num == 0)//从头向后替换 替换第一个
				{
					pagelist[j].name = handle[i];
					pagelist[j].num = 1;
					break;
				}
			}
			if (j == AP)//全都访问过 替换第一个
			{
				pagelist[0].name = handle[i];
				pagelist[0].num = 1;
			}
		}
		write(i);
	}
}

void OPT()//最佳置换算法
{
	int i, j;
	for (i = 0; i < AP; i++)//先把页面填满再开始替换
	{
		pagelist[i].name = handle[i];
		pagelist[i].num = 1;
		write(i);
	}
	for (; i < len; i++)//填满之后开始
	{
		for (j = 0; j < AP && (pagelist[j].name != handle[i]); j++);//查找页面是否已经在内存
		if (j == AP)//遍历完也没有找到 缺页
		{
			for (j = 0; j < AP; j++)//从头向后 计算当前到需要处理的位置的距离
			{
				pagelist[j].num = 0;
				//从当前位置直到末尾 未到下一个需要处理的位置 值就+1
				for (int k = i + 1; k < len && pagelist[j].name != handle[k]; k++, pagelist[j].num++);
			}
			int max = 0;
			for (int k = 1; k < AP; k++)//找最大的
			{
				if (pagelist[max].num < pagelist[k].num)
				{
					max = k;
				}
			}
			pagelist[max].name = handle[i];//替换最后处理到的页面
		}
		write(i);
	}

}

void input()//输入
{
	int i;
	cout << "请输入处理机处理页面的顺序,输入 0 结束" << endl;
	cin >> handle[0];
	for (i = 1; handle[i - 1] != 0; i++)
	{
		cin >> handle[i];
	}
	len = i - 1;
	cout << "请输入内存可以控制的总页面数:" << endl;
	cin >> AP;
}

void output()//输出
{
	cout << "\n处理页面顺序:" << endl << "            ";
	for (int i = 0; i < len; i++)
	{
		cout << handle[i] << "   ";
	}
	cout << endl;
	for (int i = 0; i < AP; i++)
	{
		cout << "内存页 " << i + 1 << " 号   ";
		for (int j = 0; j < len; j++)
		{
			cout << outputlist[i][j] << "   ";
		}
		cout << endl;
	}
}
int main()
{
	int cho;//选择
	int CLEAR_PERIOD;//循环周期
	cout << "请输入选择的算法:\n1.最近没有使用页面淘汰算法\n2.最佳置换算法" << endl;
	do {
		cin >> cho;
		if (cho != 1 && cho != 2)
		{
			cout << "输入不正确,请重试" << endl;
		}
		else
		{
			break;
		}
	} while (1);
	input();
	switch (cho)
	{
	case 1:
		cout << "请输入循环周期:" << endl;
		cin >> CLEAR_PERIOD;
		NUR(CLEAR_PERIOD);
		break;
	case 2:
		OPT();
		break;
	}
	output();
	return 0;
}
/*
测试数据一
1
1 4 2 5 3 3 2 2 5 0
3
5

测试数据二
2
7 5 1 2 5 3 5 4 2 3 5 3 2 1 2 5 1 7 5 1 0
3



*/

 


运行截图(测试样例见代码末):

1、最近没有使用页面淘汰算法

 2、最佳置换算法


                                  

 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【资说明】 基于C++实现操作系统进程调度可视化与模拟码+实验报告.zip 1、该资内项目代码都是经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能。 欢迎下载,欢迎交流,互相学习进步! 一、实验目的 多道系统中,进程与进程之间存在同步与互斥关系。当就绪进程数大于处理机数时,需按照某种策略决定哪些进程先占用处理机。在可变分区管理下,采用首次适应算法实现主存空间的分配和回收。 本实验模拟实现处理机调度及内存分配及回收机制,以对处理机调度的工作原理以及内存管理的工作过程进行更深入的了解。 1.实验内容 (1)选择一个调度算法,实现处理机调度; (2)结合(1)实现存储器空间的分配和回收。 二、需求分析和基本设计思想 1.需求分析 本次处理机调度模拟程序主要分为以下模块: ① 输入模块:在任意时间片可以添加新进程。 ② 挂起模块:在任意时间片可以对内存中进程进行挂起,转移至外存。 ③ 运行模块:程序核心模块,从当前就绪队列中选取优先级最高的进程运行。当就绪队列存在空闲时从后背队列/解挂程序中调取适当程序加入就绪队列;当有进程运行完成时,需释放内存,同时调取合适进程加入就绪队列。 ④ 显示模块:界面设计,显示当前各进程信息。 对于进程运行状态,分别设置四个队列进行存储: ready_queue:就绪队列,已分配内存进程。 back_queue:后备队列,由于道数限制等原因未加入内存进程。 suspend_queue:挂起队列,存储挂起进程,位于外存。 unsuspend_queue:解挂队列,但由于道数限制等原因未加入就绪队列。 free_mem_link:储存空闲内存链表。 主要算法选择: 处理机调度:抢占优先权调度算法; 主存空间的分配和回收:可变分区、首次适应算法。
好的,这是一个比较复杂的程序,需要一些时间来编写。我可以给您提供一些思路和参考代码,帮助您完成这个任务。 首先,动态存储管理是指将进程的虚拟地址空间划分为大小相等的页面,然后将这些页面映射到物理内存中的帧上。这样,进程在访问虚拟地址空间的时候,实际上是在访问物理内存中的帧。 在动态存储管理中,常用的淘汰算法有先进先出(FIFO)、最近最少使用(LRU)和最不常用(LFU)等。这里我们以LRU算法为例进行模拟。 下面是一份C语言代码,用于模拟动态存储管理中的LRU淘汰算法。该程序中,我们使用一个双向链表来维护物理内存中的页面,每当有新的页面需要加载到内存中时,就从链表的头部开始查找,将最久未使用的页面淘汰掉,并将新页面插入到链表的尾部。 ```c #include<stdio.h> #include<stdlib.h> #define PAGE_NUM 10 // 物理内存中页面的数量 #define PAGE_SIZE 1024 // 每个页面的大小(字节) // 双向链表节点 typedef struct PageNode { int page_id; // 页面号 struct PageNode* prev; // 前驱节点 struct PageNode* next; // 后继节点 } PageNode; // 创建一个空的双向链表 PageNode* create_list() { PageNode* head = (PageNode*)malloc(sizeof(PageNode)); head->prev = NULL; head->next = NULL; return head; } // 在链表尾部插入一个新的页面节点 void insert_page(PageNode* head, int page_id) { PageNode* new_node = (PageNode*)malloc(sizeof(PageNode)); new_node->page_id = page_id; new_node->prev = head->prev; new_node->next = head; head->prev->next = new_node; head->prev = new_node; } // 从链表中删除指定的页面节点 void delete_page(PageNode* node) { node->prev->next = node->next; node->next->prev = node->prev; free(node); } // 查找链表中最久未使用的页面节点 PageNode* find_oldest_page(PageNode* head) { PageNode* oldest_node = head->next; PageNode* cur_node = oldest_node->next; while (cur_node != head) { if (cur_node->last_used_time < oldest_node->last_used_time) { oldest_node = cur_node; } cur_node = cur_node->next; } return oldest_node; } int main() { PageNode* head = create_list(); // 创建一个空的双向链表 int page_table[PAGE_NUM]; // 页面表,用于记录页面是否在物理内存中 for (int i = 0; i < PAGE_NUM; i++) { page_table[i] = -1; // 初始化页面表,所有页面都不在内存中 } int access_count = 0; // 记录访问的页面数量 int page_fault_count = 0; // 记录缺页中断的次数 int page_id; // 当前访问的页面号 while (scanf("%d", &page_id) != EOF) { access_count++; // 如果页面已经在内存中,则更新页面的最近访问时间 if (page_table[page_id] != -1) { head->prev->last_used_time = access_count; continue; } // 如果内存已满,则淘汰最久未使用的页面 if (head->prev != head && page_table[page_id] == -1) { PageNode* oldest_node = find_oldest_page(head); page_table[oldest_node->page_id] = -1; delete_page(oldest_node); page_fault_count++; } // 将新页面插入到链表的尾部,并更新页面表 insert_page(head, page_id); page_table[page_id] = 1; } printf("访问的页面数量:%d\n", access_count); printf("缺页中断的次数:%d\n", page_fault_count); return 0; } ``` 这个代码实现了一个比较简单的LRU淘汰算法模拟程序,可以根据您的需要进行修改和扩展。如果您还有其他问题或需求,欢迎随时提出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值