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

本文介绍了如何编写程序实现第九章中的FIFO、OPT和LRU页面置换算法,包括随机生成页面引用串、记录算法表现、缺页计算和人机交互设计。程序通过不同算法处理缺页,计算缺页率,适用于3-7个页面帧的系统。
摘要由CSDN通过智能技术生成

一、实验目的

编写一个程序,实现第九章所述的 FIFO、OPT 和 LRU 页面置换算法。

二、实验要求

(1)首先,生成一个随机的页面引用串,其中页码的范围为 0~9。

(2)将这个随机页面引用串应用到每个算法,记录每个算法引起的缺页次数,列出每次页面置换 的换出页序号,计算缺页率。

(3)系统分配给用户的页面帧的数量可选:3~7,具体分配策略可自行定义。

(4)假设采用请求分页(按需调页)。

(5)若实现可视化效果(图形、动画展示等)有加分

三、代码说明

   全局变量说明

  

   PN表示页面访问序列的长度,程序根据PN值随机生成长度为PN的0~9的页面访问系列。

   FN表示分配给进程的内存块数

   pageSeq、frames是两个指针,代表页面访问序列数组和内存块数组。

   fault表示缺页数、change表示页面置换数、ratio表示缺页率、swap_out表示被淘汰的序列号。

  

   功能函数说明

  

   用于初始化内存,将frames数组的每一项初始化为-1。

  

   用于输出单步结果

  

   用于打印缺页次数、置换次数、缺页率

  

   用于给页面访问序列数组和内存数组初始化空间,生成长度为PN的随机页面访问序列并告诉用户所生成的页面访问序列值。

  

   用于告诉用户本程序提供了哪些功能接口,引导用户操作本程序。

  

   搜索函数

  

   检查是否缺页:当发出请求分页时,需要检查当前访问序列号是否在内存块中,如果已经存在、即命中,没有缺页;反之,则没有命中,缺页。

   寻找置换序列号:如果发生缺页,需要遍历内存块中的每一个序列号,如果在算法要求的序列中不存在,那么认为当前序列号就是最久没有被访问的,如果所有序列号在算法要求的序列中都存在,则需要找一个最久没有被访问的序列号作为淘汰序列号。特别注意的是,FIFO算法无需使用该函数,因为FIFO算法如果发生缺页,其使用的是轮流淘汰的原则。

   FIFO算法原理:

   1、初始化内存块、随机生成页面访问序列;

   2、循环取出页面访问序列中的一个值;

   3、检查是否缺页、是则使用轮流淘汰算法进行页面置换、否则直接跳过;

   4、循环上述步骤、直至没有页面访问序列需要访问。

   OPT算法原理:

   1、初始化内存块、随机生成页面访问序列;

   2、循环取出页面访问序列中的一个值;

   3、检查是否缺页、是则使用未来最久不被访问算法进行页面置换、否则直接跳过;

   4、循环上述步骤、直至没有页面访问序列需要访问。

LRU算法原理:

   1、初始化内存块、随机生成页面访问序列;

   2、循环取出页面访问序列中的一个值;

   3、检查是否缺页、是则使用过去最久不被访问算法进行页面置换、否则直接跳过;

   4、循环上述步骤、直至没有页面访问序列需要访问。

   未来最久不被访问算法原理:

   1、定义一个变量a,并初始化为一个比较小的值MINSIZE;

   2、取出内存块中的一个值b,将其与未来的访问序列比对,找出其第一次出现的位置pos,将pos与a进行比较,并将最大值赋予a,并记录b在内存块中的位置j;若匹配失败,则认为b就是最久不被访问的页面,将其淘汰,终止循环;

   3、遍历内存块中所有值,最终内存块中j对应的值就是最久不被访问的页面,将其淘汰。

过去最久不被访问算法原理:

   1、定义一个变量a,并初始化为一个比较大的值MAXSIZE;

   2、取出内存块中的一个值b,将其与过去的访问序列比对,找出其第一次出现的位置pos,将pos与a进行比较,并将最小值赋予a,并记录b在内存块中的位置j;

   3、遍历内存块中所有值,最终内存块中j对应的值就是最久不被访问的页面,将其淘汰。

四、实验结果

1、人机交互

初始化页面访问序列并告诉客户本程序的操作说明。

1、FIFO算法:

fault后面如果有数字则表明其实淘汰的页面编号,最终打印总的缺页次数、置换次数、缺页率。

               置换次数=缺页次数-内存块个数

               缺页率=缺页次数/页面访问序列的长度

2、OPT算法:

fault后面如果有数字则表明其实淘汰的页面编号,最终打印总的缺页次数、置换次数、缺页率。

               置换次数=缺页次数-内存块个数

               缺页率=缺页次数/页面访问序列的长度

3、LRU算法:

fault后面如果有数字则表明其实淘汰的页面编号,最终打印总的缺页次数、置换次数、缺页率。

               置换次数=缺页次数-内存块个数

               缺页率=缺页次数/页面访问序列的长度

五、实验代码

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
using namespace std;

#define PN 12//页面访问序列长度
#define FN 3//分配给进程的内存块数

int* pageSeq;//页面访问序列
int* frames;//内存块数组
int fault, change;//缺页次数和置换次数
float ratio;//缺页率
int swap_out;

//初始化内存块,没有被占用就初始化为-1
void clear()
{
	fault = 0;//缺页次数
	change = 0;//置换次数
	for (int i = 0; i < FN; i++) {
		frames[i] = -1;
	}
}

//输出每一步结果
void display1(int flag, int swap_out)//是否缺页,被淘汰的序列号
{
	for (int i = 0; i < FN; i++) {
		printf("-----");
	}
	printf("\n");
	
	//输出内存中存储序列号的情况
	for (int i = 0; i < FN; i++) {
		printf("|%3d|", frames[i]);
	}
	
	//是否缺页,缺页则输出fault以及被淘汰的序列号,如果为-1则不输出	
	if (flag) {
		printf("  fault");
		if (swap_out != -1) {
			printf("  %d", swap_out);
		}
	}
	printf("\n");
	for (int i = 0; i < FN; i++) {
		printf("-----");
	}
	printf("\n");
	Sleep(1000);
}

//输出缺页次数、置换次数、缺页率
void display()
{
	change = fault - FN;//除了前FN个,剩下的只要缺页都需要置换
	ratio = (float)fault / PN * 100;
	printf("------------------------------\n");
	printf("缺页次数:%d\n", fault);
	printf("置换次数:%d\n", change);
	printf("缺 页 率:%4.1f%%\n", ratio);
	printf("==============================\n");
}

//搜索内存中的序列号在访问序列中的位置,找到返回下标,否则返回-1
//p:需要找的序列号,ar:页面访问序列或者内存块数组,start:起点,end:终点
//内存块中的某个序列号在访问序列中的位置
//当前访问序列号是否在内存块中,即是否缺页
int search(int p, int* ar, int start, int end)
{
	int i, to;//to作为方向标志,to=1时,循环变量递增;to=-1时,循环变量递减
	//在OPT算法中,往后搜索,start<end,循环变量递增,to=1
	//在LRU算法中,往前搜索,start>end,循环变量递减,to=-1
	if (start > end) {
		to = -1;
	}
	else {
		to = 1;
	}

	i = start;
	while (i != end + to)
	{
		if (p == ar[i]) {//找到p则返回下标
			return i;
		}
		i = i + to;
	}
	return -1;//找不到,则返回-1
}

//OPT算法,往后搜索,淘汰最晚出现的
//sequence:页面访问序列数组,page:内存块数组
void OPT(int* sequence, int sequence_length, int* page, int page_length)
{
	int i = 0, j, flag;
	int page_num = 0;//page_num为进入内存页面数,当page_num>=page_length时,内存块满,此时缺页产生置换,且page_num的值不再增加
	int start;//搜索起点,即页面访问序列中当前页的下一位置
	int posi, pos_s_max, pos_p_max;//未来最久不使用页面在sequence和page中的位置
	clear();//内存块数据清零
	printf("页面访问过程:\n");
	printf("------------------------------\n");
	for (i = 0; i < sequence_length; i++)//扫描页面访问序列
	{
		flag = 0;//缺页标志,初值置0,不缺页
		if (search(sequence[i], page, 0, page_length - 1) == -1)//页不在内存
		{
			flag = 1;//缺页,flag置1
			fault++;//缺页+1
			if (page_num < page_length)//有空闲内存块,不需要置换
			{
				swap_out = page[page_num];
				page[page_num] = sequence[i];
				page_num++;
			}
			else//没有空闲内存块,需要置换
			{
				start = i + 1; //当前访问序列的下一个位置
				pos_s_max = -1;//被淘汰页面在访问序列sequence中的位置,初值置-1

				//对内存page中的每个页面依次查找其在访问序列sequence中(未来)第一次出现的位置,并存放在posi中
				for (j = 0; j < page_length; j++)
				{
					posi = search(page[j], sequence, start, sequence_length - 1);
					if (posi == -1)//不存在
					{
						swap_out = page[j];
						page[j] = sequence[i];//置换并终止循环
						break;
					}
					if (posi > pos_s_max)//存在,找最晚出现的序列号
					{
						pos_s_max = posi;//更新最晚出现的序列号的位置
						pos_p_max = j;//记录最晚出现的序列号在内存中的位置
					}
				}
				//说明page中所有序列号都出现过
				if (j >= page_length) {
					swap_out = page[pos_p_max];
					page[pos_p_max] = sequence[i];//将当前要访问的序列号放在内存中pos_p_max记录的位置,即最晚出现的序列号的位置
				}
			}
		}
		display1(flag, swap_out);//输出每一次内存页面情况
	}
}

//FIFO算法
//sequence:页面访问序列数组,page:内存块数组
void FIFO(int* sequence, int sequence_length, int* page, int page_length)
{
	int i, j = 0, flag;
	clear();//内存块数据清零
	printf("页面访问过程:\n");
	printf("------------------------------\n");
	for (i = 0; i < sequence_length; i++)
	{
		flag = 0;//缺页标志
		if (search(sequence[i], page, 0, page_length - 1) == -1)//是否缺页
		{
			fault++;//缺页+1
			flag = 1;
			swap_out = page[j];
			page[j] = sequence[i];
			j = (j + 1) % page_length;//j+1,循环
		}
		display1(flag, swap_out);//输出每一次内存页面情况
	}
}

//LRU算法,往前搜索,淘汰最早出现的,即最久未被访问的
//sequence:页面访问序列数组,page:内存块数组
void LRU(int* sequence, int sequence_length, int* page, int page_length)
{
	int i, j;
	int page_num = 0;//page_num>=page_length时,内存块满,此时缺页产生置换
	int flag;//缺页标志
	int posi, pos_s_max, pos_p_max;//最久未访问页面在sequence中过去的位置和在page中的位置
	clear();//清理内存块数据等
	for (i = 0; i < sequence_length; i++)
	{
		flag = 0;
		if (search(sequence[i], page, 0, page_length - 1) == -1)//是否缺页
		{
			flag = 1;
			fault++;//缺页
			if (page_num < page_length)//有空闲块,不需要置换
			{
				swap_out = page[page_num];
				page[page_num] = sequence[i];
				page_num++;//空闲块减少
			}
			else//无空闲块,需要置换
			{//在sequence中向前搜索,寻找最久未被访问的页面位置
				pos_s_max = sequence_length;//pos_s_max初值(最大值或者当前值i)
				for (j = 0; j < page_length; j++)//遍历内存块中的每一个值
				{
					posi = search(page[j], sequence, i - 1, 0);//这里与OPT不同,不会出现页面不存在的情况
					if (posi < pos_s_max)//page[j]中的值一定在访问序列中出现过,所以posi一定不等于-1
					{
						pos_s_max = posi;//更新最久未被访问的序列号的位置
						pos_p_max = j;//记录最久未被访问的序列号在内存中的位置
					}
				}
				swap_out = page[pos_p_max];//记录被淘汰的序列号
				page[pos_p_max] = sequence[i];//置换
			}
		}
		display1(flag, swap_out);//输出每一次内存页面情况
	}
}

//随机生成页面访问序列
void init()
{
	//给页面访问序列数组和内存数组初始化空间
	pageSeq = (int*)(malloc(PN * sizeof(int)));//初始化为页面访问序列长度
	frames = (int*)(malloc(FN * sizeof(int)));//初始化为内存块个数

	//随机生成序列
	for (int i = 0; i < PN; i++) {
		pageSeq[i] = rand() % 10;
	}

	printf("页面访问序列:\n\n");//输出页面访问序列
	for (int i = 0; i < PN; i++) {
		printf("%3d", pageSeq[i]);
	}
	printf("\n\n");
	printf("===============================================================\n");
}

//人机交互信息
void solve() {
	printf("【页面置换算法】\n");
	printf("序列长度:%d\n", PN);//输出访问序列长度
	printf("内存块数:%d\n", FN);//输出内存块数
	printf("======================\n\n");
	init();//随机生成页面访问序列
	//给用户介绍该程序提供了哪些操作
	printf("操作说明:\n");
	printf("    op=0  程序结束\n");
	printf("    op=1  FIFO算法\n"); 
	printf("    op=2  OPT算法\n");
	printf("    op=3  LRU算法\n");
	printf("==============================\n");
	printf("\n");
	printf("输入操作序号op:");
}

int main() {
	int op;//操作选择
	solve();//人机交互信息
	scanf_s("%d", &op);
	while (1)
	{
		system("cls");
		switch (op)
		{
		case 0:printf("\n=====程序结束!=====\n"); return 0;
		case 1:printf("\n【FIFO算法】\n"); FIFO(pageSeq, PN, frames, FN); break;//PN和FN分别代表各自数组的长度
		case 2:printf("\n【OPT算法】\n"); OPT(pageSeq, PN, frames, FN); break;//pageSeq是页面访问序列,frame是内存数组
		case 3:printf("\n【LRU算法】\n"); LRU(pageSeq, PN, frames, FN); break;
		default:printf("\n=====重新输入=====\n"); goto L1;
		}
		display();//输出缺页次数、置换次数、缺页率
	L1:     printf("\n");//若用户输入非法值,需要跳过display(),则拒绝处理,要求用户重新输入
		printf("输入操作序号num:");
		scanf_s("%d", &op);
	}
}

 

  • 29
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值