操作系统实验-页面置换算法

页面置换算法

前言:

  • 在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断。当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则叫做页面置换算法。
实验要求:
  • 设计并实现最近最久未使用页面置换(LRU)算法;
  • 实现最不常用页面置换算法(LFT),页面缓冲置换算法(PBA)和改进型CLOCK页面置
    换算法(可选);
  • 编写测试程序,对不同页面置换算法的性能进行测试和比较。
本代码实现了最佳页面置换算法(OPT),先进先出置换算法(FIFO),最不常用置换算法(LFT),最近最久未使用置换算法(LRU)以及改进型CLOCK页面置换算法。

注: 改进型CLOCK页面置换算法仅仅实现算法思想。

算法思想
- 请到: 此处查看. 不要懒,百度百科你值得拥有。

在这里插入图片描述

  • 如果代码需要在Linux内核中实现,请将页面下滑至最后,有你想要的。

在这里插入图片描述

C语言代码实现:

#include <stdio.h>
#include <stdlib.h>
int kh;
struct LNode
	{
		int data;
		int flag;//访问位
		int modify;//修改位
	};//改进型Clock算法数据结构

//输出内存块页面序号
int OutputBlockofMemory(int *BlockofMemory, int BlockCount, int ReplacePage, int PageNum)
{
	int i;

	printf("访问页面 %d 后,", PageNum);
	printf("内存中的页面号为:\t");
	for(i = 0; i < BlockCount; i++)
	{
		if(BlockofMemory[i] < 0)
			printf("#  ");
		else
			printf("%d  ", BlockofMemory[i]);
	}

	if(ReplacePage != -1)
		printf("\t淘汰页面号为:%d", ReplacePage);

	printf("\n");

	return -1;
}

//输出页面引用串号
void OutputPageNumofRef(int* PageNumofRef, int PageNumRefCount)
{
	int i = 0;
	printf("页面引用串为:\t");
	for(i = 0; i < PageNumRefCount; i++)
		printf("%d  ", PageNumofRef[i]);
	printf("\n");
}

//内存块页面号清零
void ResetBlockofMemory(int *BlockofMemory, int BlockCount)
{
	int i;
	for(i = 0; i < BlockCount; i++)
		BlockofMemory[i] = -1;
}

//判断页是否在内存中,如果页在内存中,返回1,否则返回0;
int PageInBlockofMemory(int PageNum, int *BlockofMemory, int BlockCount)
{
	int i;
	for(i = 0; i < BlockCount; i++)
		if(PageNum == BlockofMemory[i])
			return 1;
	return 0;
}
//LFT算法判断页是否在内存中,如果页在内存中,返回1,相应计数器加1,否则返回0;
int PageInBlockofMemoryLFT(int PageNum, int *BlockofMemory, int BlockCount,int *sum)
{
	int i;
	for(i = 0; i < BlockCount; i++)
		if(PageNum == BlockofMemory[i])
			{sum[i]++;
			return 1;}
	return 0;
}

//下次访问次序
//参数j:  页面在内存块中的位置
//参数i: 页面号在页面号引用串中的位置
int DistanceOpt(int *BlockofMemory, int *PageNumofRef, int j, int i, int PageNumRefCount)
{
	int k;
	for(k = i + 1; k < PageNumRefCount; k++)
		if(BlockofMemory[j] == PageNumofRef[k])
			return k;
	return PageNumRefCount;
}

//最佳页面置换算法
float Opt(int *BlockofMemory, int *PageNumofRef, int BlockCount, int PageNumRefCount)
{
	int i, j, k;
	int MaxIndex1, MaxIndex2;
	int MissCount = 0;
	int ReplacePage;
	int EmptyBlockCount = BlockCount;

	printf("**********最佳页面置换算法:**********\n");

	//输出页面引用串号
	OutputPageNumofRef(PageNumofRef, PageNumRefCount);

	for(i = 0; i < PageNumRefCount; i++)
	{
		if(!PageInBlockofMemory(PageNumofRef[i], BlockofMemory, BlockCount)) //页不在内存中
		{
			MissCount++;

			if(EmptyBlockCount > 0)
			{
				BlockofMemory[BlockCount - EmptyBlockCount] = PageNumofRef[i];
				OutputBlockofMemory(BlockofMemory, BlockCount, -1, PageNumofRef[i]);
				EmptyBlockCount--;
			}
			else
			{
				MaxIndex1 = MaxIndex2 = 0;
				//求出未来最长时间不被访问的页
				for(j = 0; j < BlockCount; j++)
				{
					MaxIndex2 = DistanceOpt(BlockofMemory, PageNumofRef, j, i, PageNumRefCount);
					if(MaxIndex1 < MaxIndex2)
					{
						MaxIndex1 = MaxIndex2;
						k = j;
					}
				}
				ReplacePage = BlockofMemory[k];
				BlockofMemory[k] = PageNumofRef[i];
				OutputBlockofMemory(BlockofMemory, BlockCount, ReplacePage, PageNumofRef[i]);
			}
		}
		else
		{
			OutputBlockofMemory(BlockofMemory,BlockCount, -1, PageNumofRef[i]);
		}
	}

	printf("缺页次数为: %d\n", MissCount);
	printf("OPT缺页率为: %.3f\n", (float)MissCount / PageNumRefCount);
	return (float)MissCount / PageNumRefCount;
}
//最不常用页面置换算法
float LFT(int *BlockofMemory, int *PageNumofRef, int BlockCount, int PageNumRefCount)
{
	int i, j, k=0,l;
	int *sum;//为每个页面设置计数器
	int MissCount = 0;
	int ReplacePage;
	int EmptyBlockCount = BlockCount;
	sum = (int*)malloc(BlockCount * sizeof(int));//生成计数器
	for(l=0;l<BlockCount;l++)
		sum[l]=0;//初始化计数器
	printf("**********最不常用页面置换算法:**********\n");

	//输出页面引用串号
	OutputPageNumofRef(PageNumofRef, PageNumRefCount);

	for(i = 0; i < PageNumRefCount; i++)
	{
		if(!PageInBlockofMemoryLFT(PageNumofRef[i], BlockofMemory, BlockCount,sum)) //页不在内存中
		{
			MissCount++;

			if(EmptyBlockCount > 0)//内存物理快有空间
			{
				BlockofMemory[BlockCount - EmptyBlockCount] = PageNumofRef[i];
				sum[BlockCount - EmptyBlockCount]++;
				OutputBlockofMemory(BlockofMemory, BlockCount, -1, PageNumofRef[i]);
				EmptyBlockCount--;
			}
			else
			{
				for(j=0;j<BlockCount;j++)
				if(sum[j]<sum[k])
				 k=j;
				 sum[k]=1;//被替换页面访问次数置1
				 ReplacePage = BlockofMemory[k];
				BlockofMemory[k] = PageNumofRef[i];
				OutputBlockofMemory(BlockofMemory, BlockCount, ReplacePage, PageNumofRef[i]);
			}
		}
		else
		{
			OutputBlockofMemory(BlockofMemory,BlockCount, -1, PageNumofRef[i]);
		}
	}

	printf("缺页次数为: %d\n", MissCount);
	printf("LFU缺页率为: %.3f\n", (float)MissCount / PageNumRefCount);
	return (float)MissCount / PageNumRefCount;
}
//先进先出页面置换算法
float Fifo(int *BlockofMemory,int *PageNumofRef,int BlockCount,int PageNumRefCount)
{
	int i;
	int ReplacePage;
	int ReplaceIndex = 0;
	int MissCount = 0;
	int EmptyBlockCount = BlockCount;

	printf("**********先进先出页面置换算法:**********\n");
	
	//输出页面引用串号
	OutputPageNumofRef(PageNumofRef,PageNumRefCount);

	for(i = 0; i < PageNumRefCount; i++)
	{
		if(!PageInBlockofMemory(PageNumofRef[i], BlockofMemory, BlockCount)) //页不在内存中
		{
			MissCount++;

			if(EmptyBlockCount > 0)
			{
				BlockofMemory[BlockCount - EmptyBlockCount] = PageNumofRef[i];
				OutputBlockofMemory(BlockofMemory, BlockCount, -1, PageNumofRef[i]);
				EmptyBlockCount--;
			}
			else
			{
				ReplacePage = BlockofMemory[ReplaceIndex];
				BlockofMemory[ReplaceIndex] = PageNumofRef[i];
				ReplaceIndex = (ReplaceIndex + 1) % BlockCount;
				OutputBlockofMemory(BlockofMemory, BlockCount, ReplacePage, PageNumofRef[i]);
			}
		}
		else
			OutputBlockofMemory(BlockofMemory, BlockCount, -1, PageNumofRef[i]);
	}
	printf("缺页次数为:%d\n", MissCount);
	printf("FIFO缺页率为:%.3f\n", (float)MissCount / PageNumRefCount);
	return (float)MissCount / PageNumRefCount;
}
//内存块页面号清零
void ResetBlockofMemoryClock(struct LNode *nodes, int BlockCount)
{
	int i;
	for(i = 0; i < BlockCount; i++)
		{
			nodes[i].data = -1;
			nodes[i].data = -1;
			nodes[i].data = -1;
		}
}
int PageInBlockofMemoryclock(int PageNum, struct LNode *LNode, int BlockCount)
{
	int i;
	for(i = 0; i < BlockCount; i++)
		if(PageNum == LNode[i].data)
			return 1;
	return 0;
}
int OutputBlockofMemoryclock(struct LNode *LNode, int BlockCount, int ReplacePage, int PageNum)
{
	int i;

	printf("访问页面 %d 后,", PageNum);
	printf("内存中的页面号为:\t");
	for(i = 0; i < BlockCount; i++)
	{
		if(LNode[i].data < 0)
			printf("#  ");
		else
			printf("%d  ", LNode[i].data);
	}

	if(ReplacePage != -1)
		printf("\t淘汰页面号为:%d", ReplacePage);

	printf("\n");

	return -1;
}
float upclock(struct LNode *LNode, int *PageNumofRef, int BlockCount, int PageNumRefCount)
{
	int i;
	int *sum;//为每个页面设置计数器
	int MissCount = 0;
	int ReplacePage;
	int EmptyBlockCount = BlockCount;
	
	printf("**********改进Clock页面置换算法:**********\n");

	//输出页面引用串号
	OutputPageNumofRef(PageNumofRef, PageNumRefCount);

	for(i = 0; i < PageNumRefCount; i++)
	{
		if(!PageInBlockofMemoryclock(PageNumofRef[i], LNode, BlockCount)) //页不在内存中
		{
			MissCount++;

			if(EmptyBlockCount > 0)//内存物理快有空间
			{
				LNode[BlockCount - EmptyBlockCount].data = PageNumofRef[i];
				LNode[BlockCount - EmptyBlockCount].flag = 1;
				if( i % 2 == 0)
					LNode[BlockCount - EmptyBlockCount].modify = 1;
				else
					LNode[BlockCount - EmptyBlockCount].modify = 0;
				OutputBlockofMemoryclock(LNode, BlockCount, -1, PageNumofRef[i]);
				EmptyBlockCount--;
			}
			else
			{
				int j = 0, flag= -1;
				while(1)
				{
					if((j / BlockCount) % 2 == 0)
					{
						if(LNode[j % BlockCount].flag == 0 && LNode[j % BlockCount].modify == 0)
						{
							flag = j % BlockCount;
							break;
						}//if
					}//if
					if((j / BlockCount) % 2 == 1)
					{
						if(LNode[j % BlockCount].flag == 0 && LNode[j % BlockCount].modify == 1)
						{
							flag = j % BlockCount;
							break;
						}//if
						else
							LNode[j % BlockCount].flag = 0;//访问位置0
					}//if
					j++;
				}//close while
				 ReplacePage = LNode[flag].data;
				LNode[flag].data = PageNumofRef[i];
				LNode[flag].flag = 1;
				if( i % 2 == 0)
					LNode[flag].modify = 1;
				else
					LNode[flag].modify = 0;
				OutputBlockofMemoryclock(LNode, BlockCount, ReplacePage, PageNumofRef[i]);
			}
		}
		else
		{
			OutputBlockofMemoryclock(LNode, BlockCount, -1, PageNumofRef[i]);
		}
	}

	printf("缺页次数为: %d\n", MissCount);
	printf("改进型clock算法缺页率为: %.3f\n", (float)MissCount / PageNumRefCount);
	return (float)MissCount / PageNumRefCount;
}
//最近最久未使用页面置换算法
void count(int l,int *f)         //数组未存满时,并且不在内存中  值最大要淘汰
	{
		int i;
		if(l<5)
		{
			f[l]=1;
			
			for(i=0;i<l;i++)
			{
				f[i]++;
			}
		}
		l++;
	}
	int count1(int *f)    //数组存满时,并且不在内存中  值最大要淘汰  b是指针
	{
		int a=0,b,i;
		for(i=0;i<5;i++)
		{
			if(f[i]>a) {a=f[i];b=i;}
		}

		for(i=0;i<5;i++)
		{
			if(i==b) {}
			else
			{
				if(f[i]<f[b]) f[i]++;
			}
		}
		f[b]=1;

		printf("%d",b);

		return b;
	}
	void count2(int l,int *f)    //在内存中
	{
		int i;
		for(i=0;i<=l;i++)
		{
			if(i==kh) {}
			else
			{
				if(f[i]<f[kh]) f[i]++;
			}
		}
		f[kh]=1;
	}
float Lru(int *BlockofMemory, int *PageNumofRef, int BlockCount, int PageNumRefCount)
{
	int i,j=1;int l=0;int f[5];
	int ReplacePage;
	int ReplaceIndex = 0;
	int MissCount = 0;
	int EmptyBlockCount = BlockCount;
	
	
	

	printf("************最近最久未使用页面置换算法:************\n");
	
	//输出页面引用串号
	OutputPageNumofRef(PageNumofRef, PageNumRefCount);

	for(i = 0; i < PageNumRefCount; i++)
	{
		if(!PageInBlockofMemory(PageNumofRef[i], BlockofMemory, BlockCount)) //页不在内存中
		{
			MissCount++;
			if(EmptyBlockCount > 0)
			{
				count(l,f);
				BlockofMemory[BlockCount - EmptyBlockCount] = PageNumofRef[i];
				OutputBlockofMemory(BlockofMemory, BlockCount, -1, PageNumofRef[i]);
				EmptyBlockCount--;
				
			}
			else
			{
				ReplacePage = BlockofMemory[count1(f)];
				BlockofMemory[count1(f)] = PageNumofRef[i];
				ReplaceIndex = (ReplaceIndex + 1) % BlockCount;
				OutputBlockofMemory(BlockofMemory, BlockCount, ReplacePage, PageNumofRef[i]);
			}
		}
		else
		{
			
			OutputBlockofMemory(BlockofMemory, BlockCount, -1, PageNumofRef[i]);
			count2(l,f);
			}
	}

	printf("缺页次数为:%d\n", MissCount);
	printf("LRU缺页率为:%.3f\n", (float)MissCount / PageNumRefCount);
	return (float)MissCount / PageNumRefCount;
}

int main()
{
	int *BlockofMemory;		//内存物理块
	const int BlockCount = 3;
	int i,j=0,k=0;
	int PageNumofRef[] = {3,5,0,5,1,0,8,2,5,1,3};  //页面号引用串
	int PageNumRefCount = sizeof(PageNumofRef) / sizeof(PageNumofRef[0]);
	float t[5];
	struct LNode *nodes = NULL;
	nodes = (struct LNode*)malloc(BlockCount * sizeof(struct LNode));
	BlockofMemory = (int*)malloc(BlockCount * sizeof(int));
	if(BlockofMemory == (int*)NULL)
	{
		printf("内存分配出错\n");
		exit(1);
	}

	ResetBlockofMemory(BlockofMemory, BlockCount);
	t[0]=Opt(BlockofMemory, PageNumofRef, BlockCount, PageNumRefCount);

	ResetBlockofMemory(BlockofMemory,BlockCount);
	t[1] =Fifo(BlockofMemory, PageNumofRef, BlockCount, PageNumRefCount);
	
	ResetBlockofMemory(BlockofMemory,BlockCount);
	t[2] =LFT(BlockofMemory, PageNumofRef, BlockCount, PageNumRefCount);

	ResetBlockofMemory(BlockofMemory,BlockCount);
	t[3]=Lru(BlockofMemory, PageNumofRef, BlockCount, PageNumRefCount);
	free(BlockofMemory);

	ResetBlockofMemoryClock(nodes, BlockCount);
	t[4] =upclock(nodes,PageNumofRef,BlockCount,PageNumRefCount);
	free(nodes);

	printf("\n");
	printf("按缺页率从小到大排序结果如下:\n");
	for(i=0;i<5;i++)
	{
		for(k=0;k<5;k++)
		{
		if(t[k]<t[j])
			j=k;
		}
		switch(j)
		{
		case 0:printf("最佳置换算法的缺页率为:%.3f\n", t[0]);break;
		case 1:printf("先进先出置换算法的缺页率为:%.3f\n", t[1]);break;
		case 2:printf("最不常用置换算法的缺页率为:%.3f\n", t[2]);break;
		case 3:printf("最近最久未使用置换算法的缺页率为:%.3f\n", t[3]);break;
		case 4:printf("改进型clock置换算法的缺页率为:%.3f\n", t[4]);break;
		}
		t[j]=99;
	}
	return 0;
}

执行结果:
在这里插入图片描述

Linux实现步骤:

  1. 启动Engintime Linux Lab。
  2. 使用“Linux011应用程序”模板新建一个Linux011应用程序项目。项目名称可以
    是“linuxapp”。
  3. 编辑LinuxApp.c文件,将main函数改为上面你复制的代码。【注】将注释全部删除,否则会报错。
  4. 按F7生成项目。
  5. 按F5启动调试
  6. 将生成的可执行文件从软盘B拷贝到硬盘,命令如下:
mcopy  b:linuxapp.exe  app
  1. 给app文件添加可执行权限,命令如下:
chmod +x  app
  1. 执行“sync”命令,将对文件的更改保存到磁盘。
  2. 查看可执行文件app的信息,
ls –l app
  1. 运行可执行文件app,分析运行结果。

执行结果:
在这里插入图片描述
【注】由于不能滑动,只有这么大,不要见怪。
在这里插入图片描述

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值