操作系统(页面置换)

页面置换算法

  • 一、实验目的
  • 二、实验内容
  • 三、实验准备
    • 1、先进先出(FIFO)页面置换算法
    • 2、最佳(Optimal)置换算法
    • 3、最近最久未使用LRU(Least Recently Used)置换算法
  • 四、实验要求
    • 1、数据结构
    • 2、程序流程图
      • 运行结果
  • 总结

一、实验目的

1、加深对页面置换算法的理解。
2、掌握几种页面置换算法的实现方法。
3、通过实验对比各种置换算法的优劣势。

二、实验内容

  参考用C语言实现的先进先出算法FIFO的代码,实现最佳置换算法OPT和最近最少使用算法LRU。使得随机给出一个页面执行序列,计算不同置换算法的缺页数,缺页率和命中率。

三、实验准备

1、先进先出(FIFO)页面置换算法

  这是最早出现的置换算法。该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。该算法实现简单,只需把一个进程已调入内存的页面,按先后次序链接成一个队列,并设置一个指针,称为替换指针,使它总是指向最老的页面。但该算法与进程实际运行的规律不相适应,因为在进程中,有些页面经常被访问,比如,含有全局变量、常用函数、例程等的页面,FIFO 算法并不能保证这些页面不被淘汰。
  这里,我们仍用上面的例子,但采用 FIFO 算法进行页面置换。当进程第一次访问页面 2 时,将把第 7 页换出,因为它是最先被调入内存的;在第一次访问页面 3 时,又将把第 0 页换出, 因为它在现有的 2, 0, 1 三个页面中是最老的页。 由下图可以看出,利用 FIFO 算法时进行了 12 次页面置换,比最佳置换算法正好多一倍。
在这里插入图片描述

2、最佳(Optimal)置换算法

  最佳置换算法是由 Belady 于 1966 年提出的一种理论上的算法。 其所选择的被淘汰页面,将是以后永不使用的,或许是在最长(未来)时间内不再被访问的页面。采用最佳置换算法,通常可保证获得最低的缺页率。但由于人们目前还无法预知一个进程在内存的若干个页面中,哪一个页面是未来最长时间内不再被访问的,因而该算法是无法实现的,但可以利用该算法去评价其它算法。现举例说明如下。
  假定系统为某进程分配了三个物理块,并考虑有以下的页面号引用串:
  7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1
  进程运行时,先将 7,0,1 三个页面装入内存。以后,当进程要访问页面 2 时,将会产生缺页中断。 此时 OS 根据最佳置换算法, 将选择页面 7 予以淘汰。 这是因为页面 0 将作为第 5 个被访问的页面,页面 1 是第 14 个被访问的页面,而页面 7 则要在第 18 次页面访问时才需调入。 下次访问页面 0 时, 因它已在内存而不必产生缺页中断。当进程访问页面 3时,又将引起页面 1 被淘汰;因为,它在现有的 1,2,0 三个页面中,将是以后最晚才被访问的。如下图示出了采用最佳置换算法时的置换图。由图可看出,采用最佳置换算法发生了 6 次页面置换。
在这里插入图片描述

3、最近最久未使用LRU(Least Recently Used)置换算法

  FIFO 置换算法性能之所以较差,是因为它所依据的条件是各个页面调入内存的时间,而页面调入的先后并不能反映页面的使用情况。最近最久未使用(LRU)的页面置换算法,是根据页面调入内存后的使用情况进行决策的。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU 置换算法是选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最久未使用的页面予以淘汰。
  利用 LRU 算法对上例进行页面置换的结果如图所示。当进程第一次对页面 2 进行访问时,由于页面 7 是最近最久未被访问的,故将它置换出去。当进程第一次对页面 3进行访问时,第 1 页成为最近最久未使用的页,将它换出。由图可以看出,前 5 个时间的图像与最佳置换算法时的相同,但这并非是必然的结果。因为,最佳置换算法是从“向后看”的观点出发的,即它是依据以后各页的使用情况;而 LRU 算法则是“向前看”的,即根据各页以前的使用情况来判断,而页面过去和未来的走向之间并无必然的联系。
在这里插入图片描述

四、实验要求

1、分析程序所定义使用的数据结构;
2、分析程序的结构,并画出程序流程图;
3、撰写实验报告;

1、数据结构

typedef struct pageType
{
	int num;//页号
	int time;//等待时间,LRU算法会用到这个属性
}Pro;
int pageNum;//系统分配给作业的主存中的页面数
int memoryNum;//可用内存页面数
void print(Pro*page1);//打印当前主存中的页面
int Search(int num1,Pro*memory1);//在页面集memory1中查找num1,如果找到,返回其在memory1中的下标,否则返回-1

2、程序流程图

在这里插入图片描述获取本地时间代码

void Time()
{
	time_t t;//将t声明为时间变量
    struct tm *p;//struct tm是一个结构体,声明一个结构体指针
    time(&t);
    p=localtime(&t);//获得当地的时间
    int s = 7;//定义一个值
    int k = 7;
    int sum;//计算出k和s,自己的学号是sum
    sum = s * k;
    printf("\n");
    printf("          学号展示\n",sum);
    printf("          自己的姓名\n");
    printf("\n");
    printf("操作系统实验展示于%d年%d月%d日 %d时%d分%d秒\n",1900 + p -> tm_year, 1 + p -> tm_mon, p -> tm_mday, p -> tm_hour, p -> tm_min, p -> tm_sec);
    //输出当前本地的时间 
}

全部代码

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

typedef struct pageType
{
	int num;//页号
	int time;//等待时间,LRU算法会用到这个属性
}Pro;

int pageNum;//系统分配给作业的主存中的页面数
int memoryNum;//可用内存页面数

void print(Pro*page1);//打印当前主存中的页面
int Search(int num1,Pro*memory1);//在页面集memory1中查找num1,如果找到,返回其在memory1中的下标,否则返回-1

void Time()
{
	time_t t;//将t声明为时间变量
    struct tm *p;//struct tm是一个结构体,声明一个结构体指针
    time(&t);
    p=localtime(&t);//获得当地的时间
    int s = 7;
    int k = 7;
    int sum;
    sum = s * k;
    printf("\n");
    printf("          自己的学号%d\n",sum);
    printf("          自己的姓名\n");
    printf("\n");
    printf("操作系统实验展示于%d年%d月%d日 %d时%d分%d秒\n",1900 + p -> tm_year, 1 + p -> tm_mon, p -> tm_mday, p -> tm_hour, p -> tm_min, p -> tm_sec);
    //输出当前本地的时间 
}

int main(void)
{
	int i = 0;
	int curmemory;//调入主存中的页面个数
	int missNum;//缺页次数
	float missRate;//缺页率
	char c;//得到用户的输入字符,来选择相应的置换算法
	
	Pro *page;//作业页面集
	Pro *memory;//内存页面集
	
	printf("输入系统分配给作业的主存中的页面数:\n");
	scanf("%d",&pageNum);
	printf("输入内存页面数:\n");
	scanf("%d",&memoryNum);
	
	page = (Pro*)malloc(sizeof(Pro) * pageNum);
	memory = (Pro*)malloc(sizeof(Pro) * memoryNum);
	
	for(i = 0; i < pageNum; i++)
	{
		printf("第%d个页面号为:",i);
		scanf("%d", &page[i].num);
		page[i].time = 0;//等待时间开始默认为0
	}
		do{
			for(i = 0; i < memoryNum; i++)//初始化内存中页面
			{
				memory[i].num = -1;//页面为空用-1表示
				memory[i].time = -1;//
			}
		Time(); 			
		printf("请选择以下功能菜单进行演示:\n");
		printf("*****F:FIFO页面置换算法*****\n");
		printf("*****O:Optimal置换算法*****\n");
		printf("*****L:LRU页面置换算法*****\n");
		printf("*****请输入学号结束:\n");
		
		getchar();
		scanf("%c",&c);
		
		i = 0;
		curmemory = 0;
		
		if(c =='F')//FIFO页面置换
		{
			missNum = 0;
			printf("先进先出页面置换情况:\n");\
			printf("置换的页面号    物理块1    物理块2    物理块3\n");
			for(i = 0; i < pageNum; i++)
			{
				if(Search(page[i].num,memory)<0)//若在主存中没有找到该页面
				{
					missNum++;
					memory[curmemory].num = page[i].num;
					print(memory);
					curmemory = (curmemory+1) % memoryNum;
				}	
			}
			missRate = (float)missNum / pageNum;
			printf("缺页次数:%d缺页率:%f\n",missNum,missRate);
		}
		
		if(c =='O')//OPT页面置换
		{
			missNum = 0;
			curmemory = 0;
			printf("Optimal页面置换情况:   \n");
			printf("置换的页面号    物理块1    物理块2    物理块3\n");
			for (i = 0; i < pageNum; i++)
			{
				if (Search(page[i].num, memory) < 0)//若在内存中没有找到该页面
				{
				//找出未来最长时间内不再被访问的页面
				int index;
				int optimal = 0;
				for (int k = 0; k < memoryNum; k++)
				{
					if (memory[k].num == -1)
					{
						curmemory = k;
						break;
					}
					index = 0;       //页面k在未来tem时间内不会出现
					int j;
					for (j = i + 1; j < pageNum; j++)
					{
						if (page[j].num == memory[k].num)
						{
							if (index > optimal)
							{
								optimal = index;
								curmemory = k;
							}
						break;
						}
						else index++;
					}
					if (j == pageNum)
					{
						optimal = index;
						curmemory = k;
					}
				}
					missNum++;
					memory[curmemory].num = page[i].num;
					print(memory);
				}
			}//end for
			missRate = (float)missNum / pageNum;
			printf("缺页次数:%d   缺页率:  %f\n", missNum, missRate);
		}//endif
		
		if (c == 'L') //LRU页面置换算法
		{
			missNum = 0;
			curmemory = 0;
			
			printf("LRU页面置换情况:   \n");
			printf("置换的页面号    物理块1    物理块2    物理块3\n");
			for (i = 0; i < pageNum; i++)
			{
				int rec = Search(page[i].num, memory);
				if (rec < 0)    //若在内存中没有找到该页面
				{
					missNum++;
					for (int j = 0; j < memoryNum; j++)     //找出最近最久未使用的页面
					if (memory[j].time == -1) 
					{
						curmemory = j;break;
					}
					else 
					if (memory[j].time > memory[curmemory].time)
					curmemory = j;
					
					memory[curmemory].num = page[i].num;
					memory[curmemory].time = 0;
					print(memory);
				}
				else memory[rec].time = 0;
				
				for (int j = 0; j < memoryNum; j++)     //内存中的所有页面等待时间+1 
				if (memory[j].num != -1)
				memory[j].time++;
			}//end for
			missRate = (float)missNum / pageNum;
			printf("缺页次数:%d   缺页率:  %f\n", missNum, missRate);
		}//end if
		if(c == '49')
		{
			c = 49;
			break;
		}
	} while (c == 'F' || c == 'O' || c == 'L' || c == '49');
	
	return 0;
}

void print(Pro*memory1)//打印当前的页面
{
	int j;
	for(j = 0; j < memoryNum; j++)
	printf("   %d   ",memory1[j].num);
	printf("\n");
}
//在页面集memory1中查找num1,如果找到,返回其在memory1中的下标,否则返回-1
int Search(int num1, Pro * memory1)
{
	int j;
	for(j = 0; j < memoryNum; j++)
	{
		if(num1 == memory1[j].num)
		return j;
	}
	return -1;
}


运行结果

在这里插入图片描述根据实验要求输入页面置换。

总结

代码写的不好,请多指教,有更好的代码一起交流学习。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

又菜又爱巻

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

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

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

打赏作者

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

抵扣说明:

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

余额充值