问题描述:
通过编程模拟实现请求页式存储管理的几种常用页面置换算法,了解虚拟页式存储管理的特点,掌握请求页式存储管理中几种基本页面置换算法的基本思想和实现过程,并进行比较。
设计一个虚拟存储区和内存工作区,采用固定分配局部置换策略,并使用下述算法计算采用不同页面置换算法的访问命中率。
1)最佳置换算法(OPT)
2)先进先出的算法(FIFO)
3)最近最久未使用算法(LRU)
4)最不经常使用算法(LFU)
命中率=1-页面失效次数/页地址流长度
【注】:
本实验的程序设计基本上按照实验内容进行。首先用srand( )和rand( )函数定义和产生指令序列,然后将指令序列变换成相应的页地址流,并针对不同的算法计算出相应的命中率。
(1)通过随机数产生一个指令序列,共320条指令。指令的地址按下述原则生成:
A:50%的指令是顺序执行的
B:25%的指令是均匀分布在前地址部分
C:25%的指令是均匀分布在后地址部分
具体的实施方法是:
① 在[0,319]的指令地址之间随机选取一起点m0
② 顺序执行一条指令,即执行地址为m0+1的指令
③ 在前地址[0,m0-1]中随机选取一条指令并执行,该指令的地址为m1
④ 顺序执行一条指令,其地址为m1+1
⑤在后地址[m1+2,319]中随机选取一条指令并执行
⑥重复步骤①~⑤,直到产生320次指令。
代码:
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define TOTALNUM 320 //要产生的指令的个数
#define MAXAREA 20 //内存中最大能够存放的页面数
int subscript = 0;//表示书数组下标的全局变量
int instruction[TOTALNUM];//储存每次产生的指令编号
int page[TOTALNUM];//存储页面流
int memory[MAXAREA];//内存中页面数组
void replaceArithmatic(int,int);
void insertElement(int,int,int);
void creatInstruction(int,int);
void OPT(int,int,int*);
void FIFO(int,int,int*);
void LRU(int,int,int*);
void LFU(int,int,int*);
int main(){
int i;
int mode;//选择要执行的算法
int frameNum=-1;
srand((unsigned)time(NULL));//随机数播种
creatInstruction(0,TOTALNUM);
printf("the semgment and the page:\n");
for(i=1;i<=TOTALNUM;i++){
printf("%3d.Semgment:%4d Page:%3d |\t",i,instruction[i-1],page[i-1]);
if(i%4==0)
printf("\n");
}
printf("\n==================================================================================\n");
printf("*\n");
printf("*mode: (0:OPT\t1:FIFO\t2:LRU\t3:LRF\t-1:exit)\n");
printf("*frameNum: (1~20)\n*\n");
printf("==================================================================================\n");
printf("please input the frameNum:\n");
scanf("%d",&frameNum);
while(frameNum>20||frameNum<=0){
printf("Input error! Please try again!\n");
scanf("%d",&frameNum);
}
while(mode!=-1){
printf("please input the mode:\n");
scanf("%d",&mode);
switch (mode)
{
case -1:
printf("exit!\n");
break;
case 0:
printf("============run the OPT============\n");
replaceArithmatic(frameNum,0);
break;
case 1:
printf("============run the FIFO===========\n");
replaceArithmatic(frameNum,1);
break;
case 2:
printf("============run the LRU============\n");
replaceArithmatic(frameNum,2);
break;
case 3:
printf("============run the LRF============\n");
replaceArithmatic(frameNum,3);
break;
default:
printf("Input error!\n");
break;
}
}
}
/*********************************************************************************
* 函数名:creatInstruction
* 函数的功能描述:产生需要执行的指令序列以及它对应的页表中的页
* 函数的参数:begin:随机数开始的最小值,end:随机数的最大取值
* 作者:独木春
* 版本:v1.0
* ********************************************************************************/
void creatInstruction(int begin,int end){
int m0,m1,m2;
for(;subscript<TOTALNUM-3;){
m0=(rand()%(end-begin))+begin;
instruction[subscript]=m0;
page[subscript]=m0/10;
subscript++;
instruction[subscript]=m0+1;
page[subscript]=(m0+1)/10;
subscript++;
m1=rand()%(m0-begin)+begin;
instruction[subscript]=m1;
page[subscript]=m1/10;
subscript++;
instruction[subscript]=m1+1;
page[subscript]=(m1+1)/10;
subscript++;
m2=rand()%(end-m0)+m0;
instruction[subscript]=m2;
page[subscript]=m2/10;
subscript++;
}
}
/*********************************************************************************
* 函数名:replaceArithmatic
* 函数的功能描述:执行置换算法
* 函数的参数:framNum:内存中可以存在的页面的个数,mode 执行的算法,0代表opt,1代表FIFO,2代表LRU,3代表LRF
* 作者: 独木春
* 版本:v1.0
* ********************************************************************************/
void replaceArithmatic(int frameNum,int mode){
int i,j,k;
int memoryPointer = 0;//为FIFO服务的内存指针
int full = 0;
int flag=-1;//当前内存中要交换的下标
int overflow=0;//溢出
for(i=0;i<frameNum;i++)//初始化内存
memory[i]=-1;
for(i=0;i<TOTALNUM;i++){
for(j=0;j<frameNum;j++){
if(memory[j]==-1){
if(j==frameNum-1)
full=1;
printf("interupt!\n");
memory[j]=page[i];
overflow++;
break;
}
if(full==1&&memory[j]==page[i]){
printf("\nOk\n");
break;
}
}
if(j==frameNum){ //没有命中,需要执行相应的算法
if(mode==0)
OPT(i,frameNum,&overflow);
else if(mode ==1)
FIFO(i,frameNum,&overflow);
else if(mode==2)
LRU(i,frameNum,&overflow);
else
LFU(i,frameNum,&overflow);
}
printf("step %3d: request page:%3d result: ",i,page[i]);
for(j=0;j<frameNum;j++){
printf("|%2d| ",memory[j]);
}
printf("\n");
}
printf("\nInterruption rate is %f\n",overflow*1.0/TOTALNUM );
}
/*********************************************************************************
* 函数名:OPT
* 函数的功能描述:执行OPT置换算法
* 函数的参数:station:当前要进入内存的页面在数组中的下标,framNum:内存中可以存在的页面的个数,
* *overflow:中断计数变量的地址
* 作者:独木春
* 版本:v1.0
* ********************************************************************************/
void OPT(int station,int frameNum,int* overflow){
int j,k;
int flag=-1;
printf("\ninterrupt!(OPT)\n");
for(j=station;j<TOTALNUM;j++){
for ( k= 0; k<frameNum; k++)
{
if(memory[k]==page[j]){
flag=k;
break;
}
}
}
if(flag!=-1)
memory[flag]=page[station];
else
memory[0]=page[station];
*overflow+=1;
}
/*********************************************************************************
* 函数名:FIFO
* 函数的功能描述:执行FIFO置换算法
* 函数的参数:station:当前要进入内存的页面在数组中的下标,framNum:内存中可以存在的页面的个数,
* *overflow:中断计数变量的地址
* 作者:独木春
* 版本:v1.0
* ********************************************************************************/
void FIFO(int station,int framNum,int* overflow){
printf("\ninterrupt!(FIFO)\n");
int m = *overflow%framNum;
memory[m]=page[station];
*overflow+=1;
}
/*********************************************************************************
* 函数名:LRU
* 函数的功能描述:执行最近最久未使用算法
* 函数的参数:station:当前要进入内存的页面在数组中的下标,framNum:内存中可以存在的页面的个数,
* *overflow:中断计数变量的地址
* 作者:独木春
* 版本:v1.0
* ********************************************************************************/
void LRU(int station,int framNum,int* overflow){
printf("\ninterrupt!(LRU)\n");
int i,j;
int flag = -1;
for(i=station;i>=0;i--){
for(j=0;j<framNum;j++){
if(memory[j]==page[i]){
flag=j;
break;
}
}
}
if(flag==-1)
memory[0]=page[station];
else
memory[flag]=page[station];
*overflow+=1;
}
/*********************************************************************************
* 函数名:LFU
* 函数的功能描述:执行最不经常使用算法
* 函数的参数:station:当前要进入内存的页面在数组中的下标,framNum:内存中可以存在的页面的个数,
* *overflow:中断计数变量的地址
* 作者:独木春
* 版本:v1.0
* ********************************************************************************/
void LFU(int station,int framNum,int* overflow){
printf("\ninterrupt!(LFU)\n");
int times[MAXAREA]={0};//标志页面出现次数的标志位
int max;
int flag = 0;
int i,j;
for(i=station;i>=0;i--){
for(j=0;j<framNum;j++){
if(memory[j]==page[i]){
times[j]++;
break;
}
}
}
max=times[0];
for(j=0;j<framNum;j++){
if(times[j]>max){
flag=j;
max=times[j];
}
}
memory[flag]=page[station];
*overflow+=1;
}