实验五 页面置换算法

本文介绍了如何使用C语言实现先进先出(FIFO)、最佳(OPT)和最近最少使用(LRU)三种页面置换算法,通过实验分析它们在给定页面引用序列下的缺页数、缺页率和命中率,以评估不同算法的性能。
摘要由CSDN通过智能技术生成

【实验目的】

1.加深对页面置换算法的理解。

2.掌握几种页面置换算法的实现方法。

3.通过实验比较各种置换算法的优劣。

【实验内容】

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

假定系统为某进程分配了三个物理块,并考虑有以下的页面号引用串:

7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1

【实验步骤】

1.数据结构

typedef struct item

{

int num;//页号

int time;//等待时间,LRU算法会用到这个属性

int isFind;//用于LRU算法中查找判定条件,以保证memory中的各个值只被检索一次

}Pro;

typedef struct memoryBlockIndexInPage

{

int index;

int isOccur;

}temp;//temp用于记录memory数组中的各个页号在page中出现的位置及是否在未来出现过

int pageNum;//系统分配给作业的主存中的页面数//分配的大小

int memoryNum;//可用内存页面数//可用

void print(Pro* page1);//打印当前主存中的页面

int Search(int num1,Pro* memory1);//在页面集memory1中查找num1,如果找到,返回其在memory1中的下标,否则返回-1

int compareNum_Big(int num1, int num2);//返回两个数中的较大者,该函数用于OPT置换算法

int compareNum_Small(int num1, int num2);//返回两个数中的较大者,该函数用于LRU置换算法

void print(Pro* memory1)//打印当前的页面

//在页面集memory1中查找num1,如果找到,返回其在memory1中的下标,否则返回-1

int Search(int num1, Pro* memory)

2.程序流程图

3.实验代码

#include <stdio.h>

#include <stdlib.h>

typedef struct item

{

int num;//页号

int time;//等待时间,LRU算法会用到这个属性

int isFind;//用于LRU算法中查找判定条件,以保证memory中的各个值只被检索一次

}Pro;

typedef struct memoryBlockIndexInPage

{

int index;

int isOccur;

}temp;//temp用于记录memory数组中的各个页号在page中出现的位置及是否在未来出现过

int pageNum;//系统分配给作业的主存中的页面数//分配的大小

int memoryNum;//可用内存页面数//可用

void print(Pro* page1);//打印当前主存中的页面

int Search(int num1,Pro* memory1);//在页面集memory1中查找num1,如果找到,返回其在memory1中的下标,否则返回-1

int compareNum_Big(int num1, int num2);//返回两个数中的较大者,该函数用于OPT置换算法

int compareNum_Small(int num1, int num2);//返回两个数中的较大者,该函数用于LRU置换算法

int main()

{

int i;

int curmemory;//调入主存中的页面个数//内存中已调入的进程数量

int missNum;//缺页次数

float missRate;//缺页率

char c;//得到用户的输入字符,来选择相应的置换算法

Pro* page;//作业页面集//进程

Pro* memory;//内存页面集//能容纳的最多的进程的数量

printf("输入系统分配给作业的主存中的页面数:");

scanf("%d", &pageNum);

printf("输入内存页面数:");

scanf("%d", &memoryNum);

page = (Pro*)malloc(sizeof(Pro) * pageNum);

memory = (Pro*)malloc(sizeof(Pro) * memoryNum);

for(i = 0;i < pageNum;i++)

{

printf("第%d个页面号为:\n", 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;//

}

printf("*****f:FIFO页面置换*****\n");

printf("*****o:OPT页面置换*****\n");

printf("*****l:LRU页面置换*****\n");

printf("*****请选择操作类型(f,o,l),按其它键结束******\n");

fflush(stdin);

scanf("%c", &c);

i = 0;

curmemory = 0;

if(c == 'f')//FIFO页面置换

{

missNum = 0;

printf("FIFO页面置换情况:\n");

printf("置换的页面号       ");

for(i = 0;i < memoryNum;i++)

printf("物理块号%d        ", i+1);

printf("\n");

printf("———————————————————————————————————\n");

for(i = 0;i < pageNum;i++)

{

if(Search(page[i].num, memory) < 0)//若在主存中没有找到该页面

{

missNum++;

if(i < 3)

printf("      —              ");

else

printf("      %2d              ", memory[curmemory].num);//输出被置换的页号

memory[curmemory].num = page[i].num;//内存[内存中已调入进程的数量].页号 = 录入进程的页号

print(memory);

printf("———————————————————————————————————\n");

curmemory = (curmemory+1) % memoryNum;

}

}//endfor

missRate = (float)missNum  / pageNum;

printf("缺页次数:%d\t缺页率:%f\n", missNum, missRate);

}//endif

if(c == 'o')//OPT页面置换

{

missNum = 0;

printf("Optimal页面置换情况: \n");

printf("置换的页面号       ");

for(i = 0;i < memoryNum;i++)

printf("物理块号%d        ", i+1);

printf("\n");

printf("———————————————————————————————————\n");

for(i = 0;i < pageNum;i++)

{

if(Search(page[i].num, memory) < 0)//若在主存中没有找到该页面

{

missNum++;

if(i < 3)

{

printf("      —              ");

memory[curmemory].num = page[i].num;//内存[内存中已调入进程的数量].页号 = 录入进程的页号

print(memory);

printf("———————————————————————————————————\n");

curmemory = (curmemory+1) % memoryNum;

}

else

{

temp tempRecord[3] = {{0,0},{0,0},{0,0}};

//查找要置换的页号

int j, k, comparatorCount = 0;//comparatorCounter记录要比较的值的数量

for(j = 0;j < memoryNum;j++)

{

for(k = i + 1;k < pageNum;k++)

{

if(page[k].num == memory[j].num)//如果未来的页面在内存块中

{

tempRecord[j].index = k;//记下该未来页面的下标

tempRecord[j].isOccur = 1;//tempRecord[j]在未来出现了

comparatorCount++;

break;

}

}

}

//从tempRecord数组中找出要置换的目标索引

int target_InsteadIndex = 0;

switch(comparatorCount)

{

case 0:

break;

case 1:

case 2:

for(j = 0;j < 3;j++)

{

if(tempRecord[j].isOccur == 0)//如果这个页号在未来没有出现

{

curmemory = j;

break;

}

}

break;

case 3:

target_InsteadIndex = compareNum_Big(compareNum_Big(tempRecord[0].index, tempRecord[1].index), tempRecord[2].index);

break;

}

//找出memory中要换出的下标

for(j = 0;j < memoryNum;j++)

{

if(memory[j].num == page[target_InsteadIndex].num)

{

curmemory = j;

break;

}

}

printf("      %2d              ", memory[curmemory].num);//输出被置换的页号

memory[curmemory].num = page[i].num;//内存[内存中已调入进程的数量].页号 = 录入进程的页号

print(memory);

printf("———————————————————————————————————\n");

}

}

}//endfor

missRate = (float)missNum  / pageNum;

printf("缺页次数:%d\t缺页率:%f\n", missNum, missRate);

}//endif

if(c == 'l')//LRU页面置换

{

int j, k;

missNum = 0;

printf("LRU页面置换情况:\n");

printf("置换的页面号       ");

for(i = 0;i < memoryNum;i++)

printf("物理块号%d        ", i+1);

printf("\n");

printf("———————————————————————————————————\n");

for(i = 0;i < pageNum;i++)

{

if(Search(page[i].num, memory) < 0)//若在主存中没有找到该页面

{

missNum++;

if(i < 3)

{

printf("      —              ");

memory[curmemory].num = page[i].num;//内存[内存中已调入进程的数量].页号 = 录入进程的页号

curmemory = (curmemory+1) % memoryNum;

}

else

{

for(j = i-1;j >= 0;j--)//遍历当前要插入的页号位置之前的页号

{

for(k = 0;k < memoryNum;k++)//遍历内存块中的页

{

if(page[j].num == memory[k].num && memory[k].isFind != 1)//如果之前的页号被访问过

{

memory[k].time = j;

memory[k].isFind = 1;

break;

}

}

}

int minTime = compareNum_Small(compareNum_Small(memory[0].time, memory[1].time), memory[2].time);

for(j = 0;j < memoryNum;j++)

{

if(memory[j].time == minTime)

{

curmemory = j;

break;

}

}

printf("      %2d              ", memory[curmemory].num);//输出被置换的页号

memory[curmemory].num = page[i].num;//内存[内存中已调入进程的数量].页号 = 录入进程的页号

}

print(memory);

printf("———————————————————————————————————\n");

for(j = 0;j < memoryNum;j++)

{

memory[j].isFind = 0;

}

}

}//endfor

missRate = (float)missNum  / pageNum;

printf("缺页次数:%d\t缺页率:%f\n", missNum, missRate);

}//endif

}while(c == 'f' || c == 'l' || c == 'o');

return 0;

}

void print(Pro* memory1)//打印当前的页面

{

int j;

for(j = 0;j < memoryNum;j++)

printf("%2d               ", memory1[j].num);

printf("\n");

}

//在页面集memory1中查找num1,如果找到,返回其在memory1中的下标,否则返回-1

int Search(int num1, Pro* memory)

{

int j;

for(j = 0;j < memoryNum;j++)

{

if(num1 == memory[j].num)

return j;

}

return -1;

}

int compareNum_Big(int num1, int num2)

{

return num1 >= num2 ? num1 : num2;

}

int compareNum_Small(int num1, int num2)

{

return num1 <= num2 ? num1 : num2;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值