C语言模拟OS虚拟内存页面置换算法OPT+FIFO+LRU

在进程运行过程中,若所要访问的页面不在内存,而需把它调入内存,但内存已无空闲区间时,为了保证该进程能正常运行,系统必须从内存中调出一页程序或数据送到磁盘空间的对换区中。将那个页面换出,需要根据一定的算法来确定。这就是页面置换算法。
最佳(Optimal)置换算法,选择的淘汰页将是以后永久不使用的,或许是在最长时间内不再访问的页面。这种算法可以保证最低的缺页率,但该算法真实情况下无法实现,可以作为评价其他算法的标准。
先进先出(FIFO)页面置换算法,总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以换出。只需把一个进程已调入的页面连成一个队列,每次换出队首进程。这种算法与实际进程运行规律不适应。
LRU(Least Recently Used)置换算法,选择最近最久未使用的页面予以换出。该算法赋予每个页面访问字段,用来记录一个页面上一次被访问以来的时间t。淘汰时选择t最大的页面换出。
具体代码如下:

#include <iostream>
#include <stdio.h>
#include <queue>
#include <stdlib.h>
#include <string.h>
using namespace std;
#define MaxNumber 100

int MinBlockNum, PageNum, LackPageNum; //物理块数,页面个数,缺页数
int *MinBlock;//物理块数组
double LackPageRate; //缺页率
int PageOrder[MaxNumber]; //页面序列
int *PageDisCount; //当前内存距离下一次出现的距离
int *LRUtime;  //存储各个页面最近使用情况

void Enter();  //输入物理块数、页面号顺序
void FIFO();    //先进先出FIFO
void OPT();     //最佳置换OPT
void LRU();    //最近最久未使用LRU
void display();  //显示执行结果
int find(int* a, int x); //查看页面在物理块中是否存在
int OPTCalculateInstance(int i, int j, int* a); //OPT向后计算距离
int LRUCalculateInstance(int i, int j, int* a); //LRU向前计算距离
int max_index(int* a); //找最大值下标

int main()
{
	Enter();
	//动态为数组分配空间
	MinBlock = (int*)malloc(sizeof(int) * MinBlockNum);
	PageDisCount = (int*)malloc(sizeof(int) * MinBlockNum);
	LRUtime= (int*)malloc(sizeof(int) * MinBlockNum);

	printf("\nOPI:\n");
	OPT();
	memset(MinBlock, -100, sizeof(int)* MinBlockNum); //重新初始化,以免影响后面程序执行
	printf("\nFIFO:\n");
	FIFO();
	memset(MinBlock, -100, sizeof(int) * MinBlockNum);
	printf("\nLRU:\n");
	LRU();

	//释放内存
	free(MinBlock);
	free(PageDisCount);
	free(LRUtime);
	return 0;
}


void Enter()  //初始化物理块数、页面号顺序
{
	printf("Enter MinBlockNum:");//输入物理块数
	scanf("%d", &MinBlockNum);
	printf("Enter PageNum:"); //页面数
	scanf("%d", &PageNum);
	printf("Enter PageOrder:"); //页面序列
	for (int i = 0;i < PageNum;i++) {
		scanf("%d", &PageOrder[i]);
	}	
}

int find(int *a,int x)  //查看页面在物理块中是否存在
{//把传入的页面x与物理块a中页面进行比对
	for (int i = 0;i<MinBlockNum;i++) {
		if (x == a[i]) { //找到返回
			return i;
		}	
	}
	return -1; //遍历结束表示传入的页面不在物理块中,返回-1
}

//物理块中的几个页面需要循环调用此函数,计算下一次出现的距离
int OPTCalculateInstance(int i, int j, int* a) //OPT向后计算距离
{//i表示页面序列里的下标,j表示目前物理块中的某个页面,a是页面序列
	int k = i;
	int count = 0; 
	while (k < PageNum && j != a[k]) {  //当页面序列的页面与物理块页面j不匹配时向后遍历
		count++; //距离++
		k++; //下标
	}
	if (k >= PageNum) //找到最后都没找到与j对应的页面,返回距离+1
		return count + 1;
	else
		return count; //这步说明找到了相同的页面
}

//物理块中的几个页面需要循环调用此函数,计算前一次出现的距离
int LRUCalculateInstance(int i, int j, int* a)
{//这个向前计算距离,反向遍历页面序列
	int k = i;
	int count = 0;
	while (k>=0 && j != a[k]) {
		count++;
		k--;
	}
	if (k < 0)
		return count + 1;
	else
		return count;
}

int max_index(int *a)  //找到最大值,返回数组下标
{
	int k=0;
	int max = a[0];
	for (int i = 1;i<MinBlockNum;i++) {
		if (a[i] > max) {
			max = a[i];
			k = i;
		}
	}
	return k;
}


void FIFO()    //先进先出FIFO  //10
{
	int i = 0, j = 0;
	LackPageNum = 0;
	queue<int>QBlock; //初始化队列
	while (i< PageNum)
	{
		if (-1 == find(MinBlock, PageOrder[i])) //如果要进入的页面不在物理块中
		{
			if (j < MinBlockNum) //物理块没满时
			{//页面进入物理块
				MinBlock[j++] = PageOrder[i];
				QBlock.push(PageOrder[i]);  //页面入队
			}
			else  //物理块满了,需要考虑换出的页面是哪一个
			{
				for (int k = 0;k < MinBlockNum;k++)
				{
					if (MinBlock[k] == QBlock.front()) //队首页面永远是最早进来的,替换物理块中对应的页面
					{
						MinBlock[k] = PageOrder[i]; //新页面覆盖那个进入物理块最久的页面
						QBlock.pop();
						QBlock.push(PageOrder[i]); //刚进来的页面入队
						break;
					}
				}
				
			}
			display();
			LackPageNum++; //缺页数++
		}
		else //如果要进入的页面在物理块中,表示不缺页
			printf("****************\n");
		i++;
	}
	printf("LackPageNum:%d\n", LackPageNum);
	printf("LackPageRate:%.2f\n", 1.0 * LackPageNum / PageNum);
}   

void OPT()     //最佳置换OPI  //8
{
	int i = 0, j = 0;
	LackPageNum = 0;
	while (i < PageNum) {
		if (-1 == find(MinBlock, PageOrder[i])) {  //如果要进入的页面不在物理块中
			if (j < MinBlockNum) //物理块没满时
			{//页面直接进入物理块
				MinBlock[j++] = PageOrder[i];
			}
			else  //物理块满了,需要考虑换出的页面是哪一个
			{
				for (int k = 0;k < MinBlockNum;k++)
				{//遍历物理块的页面
					PageDisCount[k] = OPTCalculateInstance(i+1, MinBlock[k], PageOrder); //计算物理块中页面与下一次的相同页面的距离
				}
				int max_i = max_index(PageDisCount); //比较物理块中页面哪个最远
				MinBlock[max_i] = PageOrder[i]; //把距离最远的页面换出去,使其被覆盖;
				
			}
			display();
			LackPageNum++; //缺页数++
		}
		else //如果要进入的页面在物理块中,表示不缺页
			printf("****************\n");
		i++; 
	}
	printf("LackPageNum:%d\n", LackPageNum);
	printf("LackPageRate:%.2f\n", 1.0*LackPageNum / PageNum);
}   

void LRU()    //最近最久未使用LRU  //11
{
	int i = 0, j = 0;
	LackPageNum = 0;
	while (i < PageNum) {
		if (-1 == find(MinBlock, PageOrder[i])) {  //如果要进入的页面不在物理块中
			if (j < MinBlockNum) //物理块没满时
			{//页面直接进入
				MinBlock[j++] = PageOrder[i];
			}
			else  //物理块满了,需要考虑换出的页面是哪一个
			{
				for (int k = 0;k < MinBlockNum;k++)
				{//遍历物理块的页面
					LRUtime[k] = LRUCalculateInstance(i-1,MinBlock[k],PageOrder); //计算物理块中页面与前一次被访问过的相同页面的距离
				}
				int max_i = max_index(LRUtime); //距离最大表示最久没有被访问
				MinBlock[max_i] = PageOrder[i]; //新页面覆盖对应页面
			}
			display();
			LackPageNum++; //缺页数++
		}
		else //如果要进入的页面在物理块中,表示不缺页
			printf("****************\n");
		i++;
	}
	printf("LackPageNum:%d\n", LackPageNum);
	printf("LackPageRate:%.2f\n", 1.0 * LackPageNum / PageNum);
} 

void display()  //显示物理块页面
{
	for (int i = 0;i < MinBlockNum;i++) {
		if (MinBlock[i] >= 0)
			printf("%d ", MinBlock[i]);
	}
	printf("\n");
}

物理块数3,页面数20。
页面序列7 0 7 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
运行结果如下:

最佳算法:
在这里插入图片描述

先进先出算法:
在这里插入图片描述

最近最久未使用算法:

在这里插入图片描述

  • 17
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值