1、 实现分页式存储管理地址转换过程,将逻辑地址转换成物理地址。
2、 在此基础上实现请求分页的地址转换;实现请求页式地址转换中出现的缺页现象中,用到的先进先出、最近最久未使用、最佳置换算法。掌握内存的分配方法和虚拟存储器的概念和原理。
利用键盘输入本模拟系统分配给作业的内存物理块个数,作业在执行过程中的页面调度次序。计算出三种算法的缺页次数和缺页率。
先说下什么是页(页面):就是将用户的程序的的地址空间分成固定大小的区域,称为”页“,或者”页面“
之后将这些页离散的放进内存中,这样解决了内存的碎片问题
记得老师上课说了下这两个概念不能混,现在区分下:
在第4章存储器管理,学习了分页式存储管理方式(是为了解决内存的碎片问题)
在第5章虚拟存储器,学习了请求分页式管理方式(除了解决碎片问题外,又“扩充”了内存的大小(虚拟))
在这里为了使得固定数目的内存来运行较多的进程,增加了调页功能和页面置换功能。
页面置换用到了三种方法
1.先进先出(FIFO),最先得到内存的最先置换它
2最近最久未使用(LRU),和FIFO差不多,只是把命中的页面放在最不应该淘汰的位置(栈顶,或者栈低,不同的老师有不同的讲法),就是说新来的将最晚被淘汰
3最佳置换方法,这个只是用来评估的算法,它要预测将来谁是最迟要内存的(因为它目前不用内存,先让别人用内存),把它先淘汰。
下面是流程图,你们不要嫌弃我~我真不会把流程图插进来,只好截图了(可是本姑娘已经对齐了~)
再下面是代码~你们知道怎么插入代码么~为啥我的那么难看
写代码的过程中有几个问题,我在下面用黄色笔标注出来! 编译器vs2010
有一些全局变量是想到啥就直接加的,你们看起看可能也会非常费劲。主要注意思想,看别人代码是个超级烦的事情。我很少很少很少看别人写的代码
所以我觉得我写代码就非常罗嗦,一点不简洁。这个是我第一次发这个东西,我以后写的时候尽可能注意简洁性。
你们要是有不懂的就在下面问吧~
#include<iostream>
#include<vector>
#include<string>
using namespace std;
typedef struct Pagetable
{
int physicalblock_No;//物理块号
int state;//状态位
}PT;
typedef struct Pagetable3
{
int physicalblock_No3;//物理块号
int state3;//状态位
}PT3;
int fifo;
int lru;
int opti;
int opt[25];//保存出现过的页号
int h=0;
PT pt[100];
PT3 pt3[100];
int COUNT;
vector<int> stack;//FIFO栈
vector<int> stack2;//LRU栈
vector<int> stack3;//optimal栈
int physical_block;//内存块数
int page_size;//页大小
int pagetable_len;//页表长度
int m[8][8];//位示图
int PageAdd;//页内地址
void Inite();//初始化位示图
void showwst();//显示位视图
void showqyl();//显示缺页率
int call_in();//调入页面
void LRU(int page_no);//
void FIFO(int page_no);//
void optimal(int pageno);
void showstack();//显示栈
void showstack2();//LRU
void showstack3();//opti
int w;
void main()
{
Inite();
int logic_add;
cout<<"输入所分配的内存块数";
cin>>physical_block;
int a;
cout<<"输入页面大小(kb)";
cin>>page_size;
cout<<"输入页表长度";
cin>>pagetable_len;
int i;
for(int i=0;i<pagetable_len;i++)//最开始页表的状态位都是0
{
pt[i].state=0;
}
int PageNo;
int count=0;
do{
COUNT++;
do
{
a=0;
cout<<"输入逻辑地址";
count=count+1;
cin>>hex>>logic_add;//我在这里是以16进制的方式输入的地址,在下面的所有代码却都默认为16进制了!!!!!为何啊?
PageNo=logic_add/(1024*page_size);//页号
if(PageNo>=pagetable_len)
{
a=1;
cout<<"越界中断请重新输入"<<endl;
}
}while(a==1);
cout<<"页号"<<PageNo<<endl;
opt[h]=PageNo;
h++;
PageAdd=logic_add%(1024*page_size);//页内地址
cout<<"页内地址"<<hex<<PageAdd<<endl;
/*if(pt[PageNo].state==0)
{
cout<<"此页不在内存!正在查找是否有剩余物理块......"<<endl;
}*/
if(stack.size()==physical_block)//栈满了
{
cout<<"FIFO"<<endl;
FIFO(PageNo);
cout<<"LRU"<<endl;
LRU(PageNo);
}
else//栈没满
{
int n=0;
for(int i=0;i<stack.size();i++)
{
if(stack[i]==PageNo)
{
cout<<"命中"<<endl;
cout<<"物理地址"<<endl<<hex<<pt[PageNo].physicalblock_No*1024+PageAdd;
n=1;
break;
}
}
if(n==0)
{
cout<<"内存有剩余,可以从位示图中分配内存(物理块号)"<<endl;
int local=call_in();//
pt[PageNo].physicalblock_No=local;//页表
cout<<"物理地址"<<endl;
cout<<hex<<local*page_size*1024+PageAdd<<endl;
stack.push_back(PageNo);
stack2.push_back(PageNo);
stack3.push_back(PageNo);
cout<<"FIFO"<<endl;
showstack();
cout<<"LRU"<<endl;
showstack2();
cout<<"最佳置换"<<endl;
showstack3();
pt[PageNo].physicalblock_No=local;
pt[PageNo].state=1;
pt3[PageNo].physicalblock_No3=local;
pt3[PageNo].state3=1;
}
}
cout<<"是否继续输入 1是 2否"<<endl;
cin>>i;
}while(i!=2);
cout<<"最佳置换"<<endl;
for(w=physical_block;w<COUNT;w++)
{
optimal(opt[w]);
}
showqyl();
system("pause");
}
void showqyl()
{ //这个代码,就是我刚才说的默认为16进制,害得我必须加上dec(10进制输出)
cout<<"FIFO"<<"缺页率:"<<dec<<fifo+physical_block<<"/"<<dec<<COUNT<<endl;
cout<<"LRU"<<"缺页率:"<<dec<<lru+physical_block<<"/"<<dec<<COUNT<<endl;
cout<<"optimal"<<"缺页率"<<dec<<opti+physical_block<<"/"<<dec<<COUNT<<endl;
}
int call_in()//位视图是8*8的
{
int loc;
for(int h=2;h<8;h++)
for(int lie=0;lie<8;lie++)
{
if(m[h][lie]==0)
{
loc=(((8*h)+lie)+1);
cout<<dec<<loc<<"号内存可以分配"<<endl;
m[h][lie]=1;
h=8;
break;
}
}
showwst();
return loc;
}
void Inite()
{
int h=2;
for(int i=0;i<2;i++)//给最开始的前2行赋值为1,系统区
{
for(int j=0;j<8;j++)
{
m[i][j]=1;
}
}
do{
int a[32];
int i=0;
long num;
num=rand()%128;
//我在想各种方式变成2进制,什么atoi itoa 各应死了,都不如自己写一个进制转换
while(num>=1)//算出2进制数
{
a[i]=num%2;
num=num/2;
i++;
}
//不足8位在前面补0
if(i<8)
{
for(int j=i;j<=7;j++)
{
a[j]=0;
}
}
for(i=7;i>=0;i--)
{
m[h][i]=a[i];
}
h++;
}while(h<8);
for(int h=0;h<8;h++)//行
{
for(int l=0;l<8;l++)//列
{
cout<<m[h][l];
}
cout<<endl;
}
}
void FIFO(int page_no)
{
int a=0;
for(vector<int>::iterator it = stack.begin();it!=stack.end();++it)
{
if(page_no==*it)
{
cout<<"命中"<<endl;
cout<<"物理地址"<<endl<<hex<<pt[page_no].physicalblock_No*1024*page_size+PageAdd<<endl;
a=1;
break;
}
}
if(a==0)
{
fifo++;
vector<int>::iterator it = stack.begin();
pt[page_no].physicalblock_No=pt[*it].physicalblock_No;
cout<<"物理地址"<<endl;
cout<<hex<<pt[page_no].physicalblock_No*page_size*1024+PageAdd<<endl;
stack.erase(it);
stack.push_back(page_no);
pt[page_no].state=0;
}
showstack();
}
void showstack()
{
for(int i=stack.size()-1;i>=0;i--)
{
cout<<stack[i]<<endl;
}
cout<<endl;
}
void showstack2()
{
for(int i=stack2.size()-1;i>=0;i--)
{
cout<<stack2[i]<<endl;
}
cout<<endl;
}
void showstack3()
{
for(int i=stack3.size()-1;i>=0;i--)
{
cout<<stack3[i]<<endl;
}
cout<<endl;
}
void LRU(int page_no)
{
int a=0;
for(vector<int>::iterator it = stack2.begin();it!=stack2.end();++it)
{
if(page_no==*it)
{
cout<<"命中"<<endl;
cout<<"物理地址"<<endl<<hex<<pt[page_no].physicalblock_No*1024*page_size+PageAdd<<endl;
vector<int>::iterator it = stack2.begin();
stack2.erase(it);
stack2.push_back(page_no);
a=1;
break;
}
}
if(a==0)
{
lru++;
vector<int>::iterator it = stack2.begin();
pt[page_no].physicalblock_No=pt[*it].physicalblock_No;
cout<<"物理地址"<<endl;
cout<<hex<<pt[page_no].physicalblock_No*page_size*1024+PageAdd<<endl;
stack2.erase(it);
stack2.push_back(page_no);
}
showstack2();
}
void showwst()
{
for(int h=0;h<8;h++)//行
{
for(int l=0;l<8;l++)//列
{
cout<<m[h][l];
}
cout<<endl;
}
}
void optimal(int pageno)
{
int j=0;int a[25];int m=0;int flag=0;
for(int i=0;i<physical_block;i++)
{
if(stack3[i]==pageno)
{
cout<<"命中"<<endl;
cout<<"物理地址"<<endl<<hex<<pt3[pageno].physicalblock_No3*1024*page_size+PageAdd<<endl;
m=1;
break;
}
}
if(m==0)
{
int p;
opti++;//缺页次数
while(j<physical_block)
{
for(p=w+1;p<h;p++)//w为当前缺页位置位置的下一个
{
if(stack3[j]==opt[p])//2==2
{
a[stack3[j]]=p; //,a这个数组存的是页面是在第几次出现的,a[2]=9 表示2页在第9个出现的,a[6]=8;代表6这个页面是在第8次出现的,那么淘汰2这个页面
break; //写到这里我忽然想到了一个排序,计数排序,我不知道我为何会联想到这个伟大的算法
}
}
if(p==h)
{
//此页面以后都不会被使用
pt3[opt[w]].physicalblock_No3=pt3[stack3[j]].physicalblock_No3;
stack3[j]=opt[w];
cout<<"物理地址"<<endl;
cout<<hex<<pt3[opt[w]].physicalblock_No3*page_size*1024+PageAdd<<endl;
flag=1;
j=physical_block;
}
j++;
}
if(flag==0)
{
int max=0;int out;//要淘汰的页号
for(int i=0;i<20;i++)
{
if(a[i]>max)
{
out=i;
max=a[i];
}
}
for(int i=0;i<physical_block;i++)
{
if(stack3[i]==out)
{
pt3[pageno].physicalblock_No3=pt3[out].physicalblock_No3;
cout<<"物理地址"<<endl;
cout<<hex<<pt3[pageno].physicalblock_No3*page_size*1024+PageAdd<<endl;
stack3[i]=pageno;
}
}
}
}
showstack3();
}