页面转换算法实现(C语言)

5种页面置换算法的简单实现

页面置换算法

OPT

最佳置换算法

  • 缺点:最佳置换算法是一种理想化算法,具有较好的性能,但是实际上无法实现(无法预知一个进程中的若干页面哪一个最长时间不被访问);
  • 优点:最佳置换算法可以保证获得最低的缺页率,性能最好
void opt() //最佳转换算法,往后查找
{
	printf("--------------------------------\n");
	printf("现在执行的是最佳置换算法opt:\n");
	memset(arr, -1, sizeof(arr));
	int no = 0, tot = 0, z = 0, three = 0;
	int flag[8];
	memset(flag, 0, sizeof(flag)); //初始化一个flag数组,来确定最晚出现需要替换的点
	for (i = 0; i < M; i++)
	{
		if (no < N) //填充空数组 
		{
			arr[no++] = pageNum[i];
			tot++;
			showdata(); 
		}
		else //当数组填充满后
		{
			for (j = 0; j < N; j++)
			{
				if (arr[j] == pageNum[i])
					z = 1; //如果队列里已经存在此进程,则无需再进行页面调度
			}
			if (z == 0)
			{
				for (int k = i + 1; k < M; k++) //从下一位向后查找 
				{
					for (j = 0; j < N; j++)
					{
						if (arr[j] == pageNum[k] && three < (N-1)) //此位先出现则标记此位
						{
							if (flag[arr[j]] == 1)
								continue;
							flag[arr[j]] = 1;							
							three++;
						}
					}
				}
				for (int l = 0; l < N; l++) //遍历确定最长时间未被访问的页面
				{
					if (flag[arr[l]] == 1)
						continue;
					else         
					{
						arr[l] = pageNum[i];
						tot++;
						showdata();
					}
				}
			}
			z = 0;
			three = 0;
			memset(flag, 0, sizeof(flag));
		}
	}
	printf("页面置换的次数为:%d\n", tot);
	double rate = (double)tot / M * 100;
	printf("OPT缺页率为:%.2lf%%\n", rate);
	printf("--------------------------------\n");
}

FIFO

先进先出算法

  • 优点:先进先出算法实现简单,是最直观的一个算法
  • 缺点:先进先出的性能最差,因为与通常页面的使用规则不符合,所以实际应用少
//FIFO先进先出算法
void fifo()
{
	printf("--------------------------------\n");
	printf("现在执行的是FIFO先进先出算法:\n");
	memset(arr, -1, sizeof(arr));
	int no = 0, z = 0, change = 0;
	for (i = 0; i < M; i++)
	{
		for (j = 0; j < N; j++)
		{
			if (arr[j] == pageNum[i])
				z = 1; //如果队列里已经存在此进程,则无需再进行页面调度
		}
		if (z == 0)
		{
			change++;
			arr[no++] = pageNum[i];
			showdata();
		}
		z = 0; //默认需要调度
		if (no == N) //队列已满,则归0从头开始,等效于队头出队
			no = 0;
	}
	printf("页面置换的次数为:%d\n", change);
	double rate = (double)change / M * 100;
	printf("FIFO缺页率为:%.2lf%%\n", rate);
	printf("--------------------------------\n");
}

LFU

最少使用置换算法

  • 缺点:并不能真正反映出页面的真实情况
  • 优点:该算法既充分利用了主存中页面调度情况的历史信息,又正确反映了程序的局部性
void lfu() //最不经常使用算法,使用次数最少算法
{
	printf("--------------------------------\n");
	printf("现在执行的是最不经常使用算法lfu:\n");
	int count[8], tot = 0, no = 0, z = 0, least = 100, mark = -1;
	memset(arr, -1, sizeof(arr));
	memset(count, 0, sizeof(count)); //用count数组记录访问次数,当访问次数相同时
	for (i = 0; i < M; i++)          //默认取索引较小的一位
	{
		if (no < N) //填充空数组 
		{
			arr[no++] = pageNum[i];
			tot++;
			count[pageNum[i]]++;
			showdata();
		}
		else
		{
			for (j = 0; j < N; j++)
			{
				if (arr[j] == pageNum[i])
				{
					z = 1; //如果队列里已经存在此进程,则无需再进行页面调度
					count[pageNum[i]]++;
				}
			}
			if (z == 0)
			{
				for (int k = 0; k < N; k++) //通过循环比较出目前访问次数最小的页面进程
				{
					if (count[arr[k]] < least)
					{
						least = count[arr[k]];
						mark = k;
					}
				}
				arr[mark] = pageNum[i];
				showdata();
				tot++;
				count[pageNum[i]]++;
			}
			z = 0;
			least = 100;
			mark = -1;
		}
	}
	printf("页面置换的次数为:%d\n", tot);
	double rate = (double)tot / M * 100;
	printf("LFU缺页率为:%.2lf%%\n", rate);
	printf("--------------------------------\n");
}

LRU

最近最久未使用置换算法

  • 优点:由于考虑程序访问的时间局部性,一般能有较好的性能;实际应用多
  • 缺点:实现需要较多的硬件支持,会增加硬件成本
void lru() //最近最久未访问算法,从当前位往前查找
{
	printf("--------------------------------\n");
	printf("现在执行的是最近最久未访问算法lru:\n");
	memset(arr, -1, sizeof(arr));
	int no = 0, tot = 0, z = 0, three = 0;
	int flag[8];
	memset(flag, 0, sizeof(flag)); //初始化一个flag数组,来确定最晚出现需要替换的点
	for (i = 0; i < M; i++)
	{
		if (no < N) //填充空数组 
		{
			arr[no++] = pageNum[i];
			tot++;
			showdata();
		}
		else //当数组填充满后
		{
			for (j = 0; j < N; j++)
			{
				if (arr[j] == pageNum[i])
					z = 1; //如果队列里已经存在此进程,则无需再进行页面调度
			}
			if (z == 0)
			{
				for (int k = i - 1; k >= 0; k--) //从上一位向前查找 
				{
					for (j = 0; j < N; j++)
					{
						if (arr[j] == pageNum[k] && three < (N - 1)) //此位先出现则标记此位
						{
							if (flag[arr[j]] == 1)
								continue;
							flag[arr[j]] = 1;
							three++;
						}
					}
				}
				for (int l = 0; l < N; l++) //遍历确定最长时间未被访问的页面
				{
					if (flag[arr[l]] == 1)
						continue;
					else
					{
						arr[l] = pageNum[i];
						tot++;
						showdata();
					}
				}
			}
			z = 0;
			three = 0;
			memset(flag, 0, sizeof(flag));
		}
	}
	printf("页面置换的次数为:%d\n", tot);
	double rate = (double)tot / M * 100;
	printf("LRU缺页率为:%.2lf%%\n", rate);
	printf("--------------------------------\n");
}

NRU

最近未用/时钟算法

  • 优点:性能和开销比较均衡
  • 缺点:未考虑页面是否被修改过
void nru() //clock置换算法/最近未用算法/NRU算法
{
	printf("--------------------------------\n");
	printf("现在执行的是clock置换算法nru:\n");
	int ask[10], no = 0, tot = 0, z = 0, mark = 0;
	memset(arr, -1, sizeof(arr));
	memset(ask, 0, sizeof(ask)); //ask数组标记是否访问,1代表最近访问,0代表未访问
	for (i = 0; i < M; i++)
	{
		if (no < N) //填充空数组 
		{
			ask[no] = 1; //初始化为最近访问
			arr[no++] = pageNum[i];
			tot++;
			showdata();
		}
		else
		{
			for (j = 0; j < N; j++)
			{
				if (arr[j] == pageNum[i])
				{
					z = 1; //如果队列里已经存在此进程,则无需再进行页面调度
					ask[j] = 1; //同时更新最近访问
				}
			}
			if (z == 0)
			{
				int k = 0;
				while (1) //通过循环找出访问位为0
				{
					for (k = 0; k < N; k++)
					{
						if (ask[k] == 0)
							goto flag;
						else if (ask[k] == 1)
							ask[k] = 0;
					}
				}
				flag:
				arr[k] = pageNum[i];
				ask[k] = 1;
				showdata();
				tot++;
			}
		}
		z = 0;
	}
	printf("页面置换的次数为:%d\n", tot);
	double rate = (double)tot / M * 100;
	printf("NRU缺页率为:%.2lf%%\n", rate);
	printf("--------------------------------\n");
}

代码实现(C语言)

#include <stdio.h>
#include <stdlib.h>

#define N 3
#define M 20
int i, j;
int arr[N];
int pageNum[M] = { 7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1 };

void showdata()
{
	for (int i = 0; i < N; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

//FIFO先进先出算法
void fifo()
{
	printf("--------------------------------\n");
	printf("现在执行的是FIFO先进先出算法:\n");
	memset(arr, -1, sizeof(arr));
	int no = 0, z = 0, change = 0;
	for (i = 0; i < M; i++)
	{
		for (j = 0; j < N; j++)
		{
			if (arr[j] == pageNum[i])
				z = 1; //如果队列里已经存在此进程,则无需再进行页面调度
		}
		if (z == 0)
		{
			change++;
			arr[no++] = pageNum[i];
			showdata();
		}
		z = 0; //默认需要调度
		if (no == N) //队列已满,则归0从头开始,等效于队头出队
			no = 0;
	}
	printf("页面置换的次数为:%d\n", change);
	double rate = (double)change / M * 100;
	printf("FIFO缺页率为:%.2lf%%\n", rate);
	printf("--------------------------------\n");
}

void opt() //最佳转换算法,往后查找
{
	printf("--------------------------------\n");
	printf("现在执行的是最佳置换算法opt:\n");
	memset(arr, -1, sizeof(arr));
	int no = 0, tot = 0, z = 0, three = 0;
	int flag[8];
	memset(flag, 0, sizeof(flag)); //初始化一个flag数组,来确定最晚出现需要替换的点
	for (i = 0; i < M; i++)
	{
		if (no < N) //填充空数组 
		{
			arr[no++] = pageNum[i];
			tot++;
			showdata(); 
		}
		else //当数组填充满后
		{
			for (j = 0; j < N; j++)
			{
				if (arr[j] == pageNum[i])
					z = 1; //如果队列里已经存在此进程,则无需再进行页面调度
			}
			if (z == 0)
			{
				for (int k = i + 1; k < M; k++) //从下一位向后查找 
				{
					for (j = 0; j < N; j++)
					{
						if (arr[j] == pageNum[k] && three < (N-1)) //此位先出现则标记此位
						{
							if (flag[arr[j]] == 1)
								continue;
							flag[arr[j]] = 1;							
							three++;
						}
					}
				}
				for (int l = 0; l < N; l++) //遍历确定最长时间未被访问的页面
				{
					if (flag[arr[l]] == 1)
						continue;
					else         
					{
						arr[l] = pageNum[i];
						tot++;
						showdata();
					}
				}
			}
			z = 0;
			three = 0;
			memset(flag, 0, sizeof(flag));
		}
	}
	printf("页面置换的次数为:%d\n", tot);
	double rate = (double)tot / M * 100;
	printf("OPT缺页率为:%.2lf%%\n", rate);
	printf("--------------------------------\n");
}

void lru() //最近最久未访问算法,从当前位往前查找
{
	printf("--------------------------------\n");
	printf("现在执行的是最近最久未访问算法lru:\n");
	memset(arr, -1, sizeof(arr));
	int no = 0, tot = 0, z = 0, three = 0;
	int flag[8];
	memset(flag, 0, sizeof(flag)); //初始化一个flag数组,来确定最晚出现需要替换的点
	for (i = 0; i < M; i++)
	{
		if (no < N) //填充空数组 
		{
			arr[no++] = pageNum[i];
			tot++;
			showdata();
		}
		else //当数组填充满后
		{
			for (j = 0; j < N; j++)
			{
				if (arr[j] == pageNum[i])
					z = 1; //如果队列里已经存在此进程,则无需再进行页面调度
			}
			if (z == 0)
			{
				for (int k = i - 1; k >= 0; k--) //从上一位向前查找 
				{
					for (j = 0; j < N; j++)
					{
						if (arr[j] == pageNum[k] && three < (N - 1)) //此位先出现则标记此位
						{
							if (flag[arr[j]] == 1)
								continue;
							flag[arr[j]] = 1;
							three++;
						}
					}
				}
				for (int l = 0; l < N; l++) //遍历确定最长时间未被访问的页面
				{
					if (flag[arr[l]] == 1)
						continue;
					else
					{
						arr[l] = pageNum[i];
						tot++;
						showdata();
					}
				}
			}
			z = 0;
			three = 0;
			memset(flag, 0, sizeof(flag));
		}
	}
	printf("页面置换的次数为:%d\n", tot);
	double rate = (double)tot / M * 100;
	printf("LRU缺页率为:%.2lf%%\n", rate);
	printf("--------------------------------\n");
}

void lfu() //最不经常使用算法,使用次数最少算法
{
	printf("--------------------------------\n");
	printf("现在执行的是最不经常使用算法lfu:\n");
	int count[8], tot = 0, no = 0, z = 0, least = 100, mark = -1;
	memset(arr, -1, sizeof(arr));
	memset(count, 0, sizeof(count)); //用count数组记录访问次数,当访问次数相同时
	for (i = 0; i < M; i++)          //默认取索引较小的一位
	{
		if (no < N) //填充空数组 
		{
			arr[no++] = pageNum[i];
			tot++;
			count[pageNum[i]]++;
			showdata();
		}
		else
		{
			for (j = 0; j < N; j++)
			{
				if (arr[j] == pageNum[i])
				{
					z = 1; //如果队列里已经存在此进程,则无需再进行页面调度
					count[pageNum[i]]++;
				}
			}
			if (z == 0)
			{
				for (int k = 0; k < N; k++) //通过循环比较出目前访问次数最小的页面进程
				{
					if (count[arr[k]] < least)
					{
						least = count[arr[k]];
						mark = k;
					}
				}
				arr[mark] = pageNum[i];
				showdata();
				tot++;
				count[pageNum[i]]++;
			}
			z = 0;
			least = 100;
			mark = -1;
		}
	}
	printf("页面置换的次数为:%d\n", tot);
	double rate = (double)tot / M * 100;
	printf("LFU缺页率为:%.2lf%%\n", rate);
	printf("--------------------------------\n");
}

void nru() //clock置换算法/最近未用算法/NRU算法
{
	printf("--------------------------------\n");
	printf("现在执行的是clock置换算法nru:\n");
	int ask[10], no = 0, tot = 0, z = 0, mark = 0;
	memset(arr, -1, sizeof(arr));
	memset(ask, 0, sizeof(ask)); //ask数组标记是否访问,1代表最近访问,0代表未访问
	for (i = 0; i < M; i++)
	{
		if (no < N) //填充空数组 
		{
			ask[no] = 1; //初始化为最近访问
			arr[no++] = pageNum[i];
			tot++;
			showdata();
		}
		else
		{
			for (j = 0; j < N; j++)
			{
				if (arr[j] == pageNum[i])
				{
					z = 1; //如果队列里已经存在此进程,则无需再进行页面调度
					ask[j] = 1; //同时更新最近访问
				}
			}
			if (z == 0)
			{
				int k = 0;
				while (1) //通过循环找出访问位为0
				{
					for (k = 0; k < N; k++)
					{
						if (ask[k] == 0)
							goto flag;
						else if (ask[k] == 1)
							ask[k] = 0;
					}
				}
				flag:
				arr[k] = pageNum[i];
				ask[k] = 1;
				showdata();
				tot++;
			}
		}
		z = 0;
	}
	printf("页面置换的次数为:%d\n", tot);
	double rate = (double)tot / M * 100;
	printf("NRU缺页率为:%.2lf%%\n", rate);
	printf("--------------------------------\n");
}

int main()
{
	fifo(); //先进先出算法
	opt(); //最佳转换算法
	lru(); //最近最久未使用
	lfu(); //最不经常使用算法
	nru(); //clock置换算法

	return 0;
}


  • 5
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeSlogan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值