目录
前言
本实验为课设内容,博客内容为部分报告内容,仅为大家提供参考,请勿直接抄袭,另外,本次实验所用平台是dev c++5.11
1 实验题目
实验八 虚拟内存系统的页面置换算法模拟
2 实验目的
通过对页面、页表、地址转换和页面置换过程的模拟,加深对虚拟页式内存管理系统的页面置换原理和实现过程的理解。
3 实验内容
3.1 步骤
(1)通过随机数产生一个指令序列,共 320 条指令。
① 50%的指令是顺序执行的;
② 25%的指令是均匀分布在前地址部分;
③ 25%的指令是均匀分布在后地址部分;
(2)实现OPT算法函数。
(3)实现LRU算法函数。
(4)实现FIFO算法函数。
(5)实现CLOCK算法函数。
3.2 关键代码
3.2.1 生成指令序列
void createOpt(){
srand((unsigned)time(0));
int i=0;
while(i<optNum){
int m=rand()%optNum; //生成[0,319]之间的随机数
if(m==optNum-1)continue; //如果生成的是319,则m+1不能放进去
opt[i++]=m+1; //把m+1放进去
if(i>=optNum)break;
int m1=rand()%(m+2); //生成[0,m+1]之间的随机数
opt[i++]=m1; //把随机的m1指令放入数组
if(i>=optNum)break;
if(m1==optNum-1)continue; //如果生成的是319,则m1+1不能放进去
opt[i++]=m1+1; //把m1+1放进去
if(i>=optNum)break;
m=(rand()%(optNum-m1-2))+m1+2; //0,319-m1-2,生成[m1+2,319]之间的随机数
opt[i++]=m;
}
}
3.2.2 OPT函数
void OPT(){
int pageNum=0;
int err=0;
for(int i=0;i<optNum;i++){
int flag=0;
for(int j=0;j<pageNum;j++){
if(opt[i]/10==page[j].index){
flag=1;
page[j].num=i;
//cout<<opt[i]/10<<"\n";
break;
}
}
if(!flag){
err++;
int max=0;
if(pageNum<proPageNum){
//程序页面没有放满
page[pageNum].index=opt[i]/10;
page[pageNum].num=i;
pageNum++;
}else{
//已满,需要置换
for(int j=0;j<pageNum;j++){
int k=i+1;
for(;k<optNum;k++){
if(page[j].index==opt[k]/10){
page[j].num=k;
break;
}
}
if(k==optNum){
page[j].num=optNum;//320
}
if(page[max].num<page[j].num){
max=j;
}
}
page[max].index=opt[i]/10;
page[max].num=i;
}
//cout<<"F "<<opt[i]/10<<"\n";
}
}
double res=(double)err*1.0/optNum;
cout<<"OPT算法的缺页次数:"<<err<<"\n";
cout<<"OPT算法的缺页率:";
printf("%.6lf\n",res);
}
3.2.3 FIFO函数
void FIFO(){
int pageNum=0;
int err=0;
for(int i=0;i<optNum;i++){
int flag=0;
for(int j=0;j<pageNum;j++){
if(opt[i]/10==page[j].index){
flag=1;
//cout<<opt[i]/10<<"\n";
break;
}
}
if(!flag){
err++;
if(pageNum<proPageNum){
//程序页面没有放满
page[pageNum++].index=opt[i]/10;
}else{
//已满,需要置换
for(int j=1;j<pageNum;j++){
page[j-1].index=page[j].index;
}
page[pageNum-1].index=opt[i]/10;
}
//cout<<"F "<<opt[i]/10<<"\n";
}
}
double res=(double)err*1.0/optNum;
cout<<"FIFO算法的缺页次数:"<<err<<"\n";
cout<<"FIFO算法的缺页率:";
printf("%.6lf\n",res);
}
3.2.4 LRU函数
void LRU(){
int pageNum=0;
int err=0;
for(int i=0;i<optNum;i++){
int flag=0;
for(int j=0;j<pageNum;j++){
if(opt[i]/10==page[j].index){
flag=1;
page[j].num=i;
//cout<<opt[i]/10<<"\n";
break;
}
}
if(!flag){
err++;
int min=0;
if(pageNum<proPageNum){
//程序页面没有放满
page[pageNum].index=opt[i]/10;
page[pageNum].num=i;
pageNum++;
}else{
//已满,需要置换
for(int j=0;j<pageNum;j++){
if(page[min].num>page[j].num){
min=j;
}
}
page[min].index=opt[i]/10;
page[min].num=i;
}
//cout<<"F "<<opt[i]/10<<"\n";
}
}
double res=(double)err*1.0/optNum;
cout<<"LRU算法的缺页次数:"<<err<<"\n";
cout<<"LRU算法的缺页率:";
printf("%.6lf\n",res);
}
3.2.5 CLOCK函数
void CLOCK(){
int pageNum=0;
int err=0;
int p=0; //指针
for(int i=0;i<optNum;i++){
int flag=0;
for(int j=0;j<pageNum;j++){
if(opt[i]/10==page[j].index){
flag=1;
page[j].num=1;
//cout<<opt[i]/10<<"\n";
break;
}
}
if(!flag){
err++;
if(pageNum<proPageNum){
//程序页面没有放满
page[pageNum].index=opt[i]/10;
page[pageNum].num=1;
pageNum++;
p=(p+1)%proPageNum;
}else{
//已满,需要置换
for(;;p=(p+1)%proPageNum){
//在环缓冲区找第一个0
if(page[p].num==1){
page[p].num=0;
}else{
//找到第一个0,替换
page[p].index=opt[i]/10;
page[p].num=1;
p=(p+1)%proPageNum;
break;
}
}
}
//cout<<"F "<<opt[i]/10<<"\n";
}
}
double res=(double)err*1.0/optNum;
cout<<"CLOCK算法的缺页次数:"<<err<<"\n";
cout<<"CLOCK算法的缺页率:";
printf("%.6lf\n",res);
}
4 实验结果与分析
根据指导书要求,若访问的指令已在内存中就直接输出其物理地址,若不在内存中,则发生缺页先输出F,置换后再输出其物理地址,运行结果如下面两张图片所示,经统计和计算,每个算法的缺页次数和缺页率是正确的。
图1.1 OPT算法和FIFO算法
图1.2 LRU和CLOCK算法
5 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define optNum 320 // 指令数
#define proPageNum 4 //程序可用页数
#define pageOptNum 10 //一页的指令数
struct memClock{
int index; //页号
int num; //使用次数
};
int test[]={20,30,20,10,50,20,40,50,30,20,50,20};
memClock test1[]={{20,0},{30,0},{20,0},{10,0},{50,0},{20,0},{40,0},{50,0},{30,0},{20,0},{50,0},{20,0}};
int opt[optNum]; //指令数数组
memClock page[proPageNum]; //程序可用页面
void createOpt(){
srand((unsigned)time(0));
int i=0;
while(i<optNum){
int m=rand()%optNum; //生成【0,319】之间的随机数
if(m==optNum-1)continue; //如果生成的是319,则m+1不能放进去
opt[i++]=m+1; //把m+1放进去
if(i>=optNum)break;
int m1=rand()%(m+2); //生成【0,m+1】之间的随机数
opt[i++]=m1; //把随机的m1指令放入数组
if(i>=optNum)break;
if(m1==optNum-1)continue; //如果生成的是319,则m1+1不能放进去
opt[i++]=m1+1; //把m1+1放进去
if(i>=optNum)break;
m=(rand()%(optNum-m1-2))+m1+2; //0,319-m1-2,生成【m1+2,319】之间的随机数
opt[i++]=m;
}
}
void OPT(){
int pageNum=0;
int err=0;
for(int i=0;i<optNum;i++){
int flag=0;
for(int j=0;j<pageNum;j++){
if(opt[i]/10==page[j].index){
flag=1;
page[j].num=i;
cout<<opt[i]/10<<" ";
break;
}
}
if(!flag){
err++;
int max=0;
if(pageNum<proPageNum){
//程序页面没有放满
page[pageNum].index=opt[i]/10;
page[pageNum].num=i;
pageNum++;
}else{
//已满,需要置换
for(int j=0;j<pageNum;j++){
int k=i+1;
for(;k<optNum;k++){
if(page[j].index==opt[k]/10){
page[j].num=k;
break;
}
}
if(k==optNum){
page[j].num=optNum;//320
}
if(page[max].num<page[j].num){
max=j;
}
}
page[max].index=opt[i]/10;
page[max].num=i;
}
cout<<"F "<<opt[i]/10<<" ";
}
}
double res=(double)err*1.0/optNum;
cout<<endl<<"OPT算法的缺页次数:"<<err<<"\n";
cout<<"OPT算法的缺页率:";
printf("%.6lf\n",res);
}
void FIFO(){
int pageNum=0;
int err=0;
for(int i=0;i<optNum;i++){
int flag=0;
for(int j=0;j<pageNum;j++){
if(opt[i]/10==page[j].index){
flag=1;
cout<<opt[i]/10<<" ";
break;
}
}
if(!flag){
err++;
if(pageNum<proPageNum){
//程序页面没有放满
page[pageNum++].index=opt[i]/10;
}else{
//已满,需要置换
for(int j=1;j<pageNum;j++){
page[j-1].index=page[j].index;
}
page[pageNum-1].index=opt[i]/10;
}
cout<<"F "<<opt[i]/10<<" ";
}
}
double res=(double)err*1.0/optNum;
cout<<endl<<"FIFO算法的缺页次数:"<<err<<"\n";
cout<<"FIFO算法的缺页率:";
printf("%.6lf\n",res);
}
void LRU(){
int pageNum=0;
int err=0;
for(int i=0;i<optNum;i++){
int flag=0;
for(int j=0;j<pageNum;j++){
if(opt[i]/10==page[j].index){
flag=1;
page[j].num=i;
cout<<opt[i]/10<<" ";
break;
}
}
if(!flag){
err++;
int min=0;
if(pageNum<proPageNum){
//程序页面没有放满
page[pageNum].index=opt[i]/10;
page[pageNum].num=i;
pageNum++;
}else{
//已满,需要置换
for(int j=0;j<pageNum;j++){
if(page[min].num>page[j].num){
min=j;
}
}
page[min].index=opt[i]/10;
page[min].num=i;
}
cout<<"F "<<opt[i]/10<<" ";
}
}
double res=(double)err*1.0/optNum;
cout<<endl<<"LRU算法的缺页次数:"<<err<<"\n";
cout<<"LRU算法的缺页率:";
printf("%.6lf\n",res);
}
void CLOCK(){
int pageNum=0;
int err=0;
int p=0; //指针
for(int i=0;i<optNum;i++){
int flag=0;
for(int j=0;j<pageNum;j++){
if(opt[i]/10==page[j].index){
flag=1;
page[j].num=1;
cout<<opt[i]/10<<" ";
break;
}
}
if(!flag){
err++;
if(pageNum<proPageNum){
//程序页面没有放满
page[pageNum].index=opt[i]/10;
page[pageNum].num=1;
pageNum++;
p=(p+1)%proPageNum;
}else{
//已满,需要置换
for(;;p=(p+1)%proPageNum){
//在环缓冲区找第一个0
if(page[p].num==1){
page[p].num=0;
}else{
//找到第一个0,替换
page[p].index=opt[i]/10;
page[p].num=1;
p=(p+1)%proPageNum;
break;
}
}
}
cout<<"F "<<opt[i]/10<<" ";
}
}
double res=(double)err*1.0/optNum;
cout<<endl<<"CLOCK算法的缺页次数:"<<err<<"\n";
cout<<"CLOCK算法的缺页率:";
printf("%.6lf\n",res);
}
int main(){
createOpt();
OPT();
FIFO();
LRU();
CLOCK();
return 0;
}