欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

操作系统实验四(页面置换算法)

程序员文章站 2022-07-14 21:36:04
...

一. 实验目的:
1、通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解。熟悉虚存管理的各种页面淘汰算法
2、通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解。
二 . 实验指导:
设计一个请求页式存储管理方案。并编写模拟程序实现之。流程图见下图。
操作系统实验四(页面置换算法)
产生一个需要访问的指令地址流。它是一系列需要访问的指令的地址。为不失一般性,你可以适当地(用人工指定地方法或用随机数产生器)生成这个序列。  页面淘汰算法分别采用 FIFO页面淘汰算法和LRU算法,并且在淘汰一页时,只将该页在页表中抹去。而不再判断它是否被改写过,也不将它写回到辅存。
具体的做法可以是:
  产生一个需要访问的指令地址流(也可以依次输入地址);
  指定合适的页面尺寸(例如以 1K或2K为1页);
  制定为进程分配的物理块数
  每访问一个地址时,首先要计算该地址所在的页的页号,然后查各物理块,判断该页是否在主存——如果该页已在主存,则打印物理快使用情况;如果该页不在主存且物理快未满,则调入一页并打印物理块使用情况;如果该页不在主存且物理块已满,则淘汰算法淘汰一页后调入所需的页,打印物理块使用情况;
逐个地址访问,直到所有地址访问完毕。

#include<bits/stdc++.h>
using namespace std;
int physicalBlock[100]; 	// 物理块队列
int physicalNum = 3;		// 物理块数
int front = 0; 				// 队头指针
int pageSize = 1; 			// 页面大小
int addressSpaceSize = 20;	// 逻辑地址空间大小
int isExist[100];		// 是否存在标记数组
int Num[100];               //访问次数
vector<int> sta;
void init()
{
	for(int i =0; i<physicalNum; i++)
	{
		physicalBlock[i]=-1;
	}
	for(int i=0; i<addressSpaceSize; i++)
	{
		isExist[i] = -1;
	}
	for(int i=0; i<physicalNum; i++)
	{
		Num[i] = -1;
	}

}
void menu()
{
	printf("\n\t页面置换算法模拟程序\n\n");
	printf("\t1. 初始化\n\n");
	printf("\t2. FIFO算法\n\n");
	printf("\t3. LFU算法\n\n");
	printf("\t4. LRU算法\n\n");
	printf("\t0. 退出\n\n");

	printf(" 注:已初始化页面大小为1kb,作业地址空间大小为20kb。\n\n");
	printf("     已为作业分配物理块数为3。页面分配策略采用固定分配局部置换。\n\n");
	printf("请输入选择: ");
}
void print()
{
	printf("\n\t物理块号\t页号\n");
	for(int i=0; i<physicalNum; i++)
	{
		printf("\t%d\t\t%d\n",i,physicalBlock[i]);
	}
}
void FIFO()
{
	int ad;
	while(1)
	{
		printf("请输入要访问的逻辑地址(-1退出): " );
		scanf("%d",&ad);
		if(ad>=1024*addressSpaceSize)
		{
			printf("错误!地址越界!!\n\n");
			continue;
		}
		//////////////////////////
		int pageNum = ad/(pageSize*1024);
		if(isExist[pageNum] != -1) // 存在
		{
			printf("\n页号:%d  该页已在内存中!\n\n",pageNum);
			print();
			printf("\n块号是:%d  物理地址是:%d\n",isExist[pageNum],ad%(pageSize*1024)+isExist[pageNum]*1024);
		}
		else // 不存在,调入
		{
			printf("\n页号:%d  该页不在内存中,调入!\n\n",pageNum);
			if(physicalBlock[front] != -1) // 非空闲
			{
				isExist[physicalBlock[front]] = -1;

			}
			physicalBlock[front] = pageNum;
			isExist[pageNum] = front;
			print();
			printf("\n块号是:%d  物理地址是:%d\n",front,ad%(pageSize*1024)+front*1024);
			front = (front+1)%physicalNum;

		}
	}

}
void print1()
{
	printf("\n\t物理块号\t页号\t访问次数\n");
	for(int i=0; i<physicalNum; i++)
	{
		printf("\t%d\t\t%d\t%d\n",i,physicalBlock[i],Num[i]);
	}
}
void LFU()
{
	int ad;
	while(1)
	{
		printf("请输入要访问的逻辑地址(-1退出): " );
		scanf("%d",&ad);
		if(ad>=1024*addressSpaceSize)
		{
			printf("错误!地址越界!!\n\n");
			continue;
		}
		int pageNum = ad/(pageSize*1024);
		if(isExist[pageNum] != -1) // 存在
		{
			printf("\n页号:%d  该页已在内存中!\n\n",pageNum);
			Num[isExist[pageNum]] ++ ;
			print1();
			printf("\n块号是:%d  物理地址是:%d\n",isExist[pageNum],ad%(pageSize*1024)+isExist[pageNum]*1024);
		}
		else // 不存在,调入
		{
			printf("\n页号:%d  该页不在内存中,调入!\n\n",pageNum);
			int min = 9999;
			int index = 0;
			// 找访问量最小
			for(int i = 0; i<physicalNum; i++)
			{
				if(Num[i]<min)
				{
					min = Num[i];
					index = i;
				}
			}
			if(physicalBlock[index] != -1) // 非空闲
			{
				isExist[physicalBlock[index]] = -1;
			}
			physicalBlock[index] = pageNum;
			isExist[pageNum] = index;
			Num[index] = 0;
			print1();
			printf("\n块号是:%d  物理地址是:%d\n",index,ad%(pageSize*1024)+index*1024);
		}
	}
}

void LRU()
{
	int ad;
	int top = 0;
	while(1)
	{
		printf("请输入要访问的逻辑地址(-1退出): " );
		scanf("%d",&ad);
		//sta.push_back(ad);
		if(ad>=1024*addressSpaceSize)
		{
			printf("错误!地址越界!!\n\n");
			continue;
		}
		int pageNum = ad/(pageSize*1024);
		if(isExist[pageNum] != -1) // 存在
		{
			printf("\n页号:%d  该页已在内存中!\n\n",pageNum);

			for(int i=0; i<sta.size(); i++)
			{
				if(sta[i] == pageNum)
				{
					sta.erase(sta.begin()+i);
					sta.push_back(pageNum);
					break;
				}
			}
			print();
			printf("\n块号是:%d  物理地址是:%d\n",isExist[pageNum],ad%(pageSize*1024)+isExist[pageNum]*1024);
		}
		else // 不存在,调入
		{
			printf("\n页号:%d  该页不在内存中,调入!\n\n",pageNum);
			int index = 0;
			if(sta.size() < physicalNum) // 物理块还没用满
			{
				sta.push_back(pageNum);
				isExist[pageNum] = sta.size()-1;
				physicalBlock[sta.size()-1] = pageNum;
				print();
			}
			else
			{

				int wait = sta[0];
				sta.erase(sta.begin());
				
				index = isExist[wait];
				isExist[wait] = -1;
				
				physicalBlock[index] = pageNum;
				isExist[pageNum] = index;
				sta.push_back(pageNum); 
				print();
			}

			printf("\n块号是:%d  物理地址是:%d\n",index,ad%(pageSize*1024)+index*1024);
		}
		top++;
	}
}

void input()
{
	printf("输入页面大小(kb): ");
	scanf("%d",&pageSize);
	printf("请输入作业逻辑地址空间大小(kb): ");
	scanf("%d",&addressSpaceSize);
	printf("输入物理块数: ");
	scanf("%d",&physicalNum);

}
int main()
{
	int n;
	init();
	while(1)
	{
		menu();
		scanf("%d",&n);
		switch (n)
		{
			case 1:
				input();
				break;
			case 2:
				FIFO();
				break;
			case 3:
				init();
				LFU();
				break;
			case 4:
				init();
				LRU();
			case 0:
				exit(0);
				break;
		}
	}
}