北京邮电大学操作系统第二次实验报告存储管理.docx
《北京邮电大学操作系统第二次实验报告存储管理.docx》由会员分享,可在线阅读,更多相关《北京邮电大学操作系统第二次实验报告存储管理.docx(14页珍藏版)》请在冰豆网上搜索。
![北京邮电大学操作系统第二次实验报告存储管理.docx](https://file1.bdocx.com/fileroot1/2022-10/19/37852c54-db7d-4e60-86c8-cb9b9596275b/37852c54-db7d-4e60-86c8-cb9b9596275b1.gif)
操作系统
实验二.存储管理
班级:
学号:
姓名:
(一)
实验目的:
通过模拟实现内存分配的伙伴算法和请求页式存储管理的几种基本页面置换算法,了解存储技术的特点。
掌握虚拟存储请求页式存储管理中几种基本页面置换算法的基本思想和实现过程,并比较它们的效率。
实验内容:
实现一个内存管理的伙伴算法,实现内存块申请时的分配和释放后的回收。
实验准备:
用随机函数仿真进程进行内存申请,并且以较为随机的次序进行释放。
对其碎片进行统计,当申请分配内存失败时区分实际空间不足和由于碎片而不能满足。
实现:
1.申请和释放序列的实现:
采用随机数生成函数产生,1—3之间的随机数,1和2时代表产生申请内存块的指令,3代表产生释放内存块的指令。
这样就可以保证产生一个随机的申请释放序列,而且因为申请的概率比释放的概率大1倍,所以肯定能保证申请完内存。
2.申请的实现
由随机数产生函数产生1到最大申请数量之间的一个值,代表申请的内存块。
用一个bool数组储存内存块的使用情况。
遍历数组查找是否有符合要求的连续内存块序列。
如果有就把对应的数组的元素改为false,并把申请记录到一个矢量中用于释放。
如果申请失败则返回失败的原因,有内存不足和没有足够的连续块两个原因。
3.释放的实现
由随机数产生函数产生1到申请的总次数之间的一个值,来决定释放哪一次申请的内存。
并根据矢量中记录的内存块的位置,和块数修改对应的数组值。
数据结构及核心函数:
#definePAGENUM100//总的块数
#defineMAXREQ5//一次最多申请的块数
#defineproduceNum(num)(rand()%num+1)
classMem
{
private:
intmemNum;
boolmem[PAGENUM];//所有内存块
vectoroccupied;
public:
Mem();
intprodecuReq(void);
intproduceRel(void);
voidrun(void);
voidshowMem(void);
voidMem:
:
showMem(void);
}
voidMem:
:
run(void)
{
srand(unsigned(time(0)));
while(true){
intop=produceNum(3);
if(op==1||op==2){//这时产生申请块,概率是释放页面的两倍
intsize=produceNum(MAXREQ);//产生申请块的个数
cout<<"申请"< boolflag;
for(inti=0;i<=PAGENUM-1;i++){
if(size>memNum){
flag=false;
break;
}
flag=true;
if(mem[i]==true){
for(intj=0;j<=size-1;j++){//检查是否有足够的连续内存
if(j+i>PAGENUM-1){
flag=false;
break;
}
if(mem[j+i]==false){
//i=i+j+1;
flag=false;
break;
}
}
if(flag){
int*temp=newint[2];
temp[0]=i;
temp[1]=size;
occupied.push_back(temp);
for(intn=0;n<=size-1;n++)
mem[i+n]=false;
break;
}
}
}
if(flag){
memNum=memNum-size;
cout<<".........申请成功,剩余"< }
else{
if(memNum cout<<".........申请失败,内存不足"< else
cout<<".........申请失败,没有足够多的连续块"< showMem();
return;
}
}
else{//这时释放块
if(occupied.size()==0)
continue;
intpage=produceNum(occupied.size());
int*temp=occupied[page-1];
memNum=memNum+temp[1];
cout<<"释放"< for(inti=temp[0];i<=temp[0]+temp[1]-1;i++)
mem[i]=true;
vector:
:
iteratorfirst=occupied.begin();
occupied.erase(first+page-1);
}
//_sleep(2000);
//getchar();
}
}
运行情况:
1.一次最多申请20块的请求情况
2.一次最多申请20块的请求失败时内存的使用情况
4.一次最多申请5块的请求情况
2.一次最多申请5块的请求失败时内存的使用情况
总结:
相对来说一次最多申请20块时比一次最多请求5块时,碎片情况要比较严重。
最多申请20块因为没有足够的连续区域而停止的概率要比最多申请5块时因为没有足够的连续区域而停止的概率大。
虽然有大块的区域没有分配,但是连续块的数量还是无法满足最多申请20块时的请求。
(二)
实验内容:
设计一个虚拟存储区和内存工作区,并使用下述算法计算访问命中率。
1)最佳置换算法(Optimal)
2)先进先出法(FisrtInFirstOut)
3)最近最久未使用(LeastRecentlyUsed)
4)最不经常使用法(LeastFrequentlyUsed)
其中,命中率=1-页面失效次数/页地址流长度。
试对上述算法的性能加以较各:
页面个数和命中率间的关系;同样情况下的命中率比较。
实验准备:
本实验中主要的流程:
首先用srand()和rand()函数定义和产生指令序列,然后将指令序列变换成相应的页地址流,并针对不同的算法计算出相应的命中率。
实现:
页面请求序列的产生:
采用指导书上产生指令的方法,先产生一个[0,1023]之间的随机数m,然后将m加1作为第一个请求,然后产生一个0到m+2之间的随机数m1,作为第二条指令,接着将m1+1作为第三条指令。
最后产生一个[m1+2,2047]之间的随机数作为第四条指令。
这样重复进行512次,一共产生了2048条指令。
接着按照指令整除64的计算方法可以获得这条指令所在的页面号。
这样便产生了2048个页面请求。
最优置换:
所有置换算法其他部分都基本相同,不同的是选择置换页面的部分。
对于最优置换,发生页错误时,使用selectBest函数选择页面。
传入start作为计算得而起始点。
设置一个time数组用来记录内存中的每一个页,在start之后第一次出现时在页面请求数组里的下标。
当然需要先将time数组初始化为INI(10000)作为初始值,这样就能代表内存中还没有页,能保证这个位置能被优先替换。
在计算完time数组后,只要在time数组中找出最大值,返回下标,这个下标就代表需要置换的内存中的页。
先进先出置换:
设置一个age数组用来记录内存中对应页的年龄,age数组初始化为INI,这样就能保证这些位置能够首先填充上页。
每次置换只要在age数组里找出最大的值(即代表这个页来得最早),返回其下标,并把这个位置置成0即可。
与最优置换不同的时,如果没有发生页错误,需要遍历age数组,把每一位都加1。
最近最久未使用:
需要设置一个useTime数组来记录上一次使用到现在的时间。
初始化为INI,这样能保证初始的值是最大的,即会被优先换出去。
每次置换时,只需要在useTime数组中找出最大的值(即上次使用时间距今最久),返回下标,并把这个位置成0。
每次发生命中时需要把除了命中页之外的所有页的useTime加1,命中页清零。
每次页错误时,需要把除了被替换页之外的所有页的useTime加1。
最不经常使用法:
需要设置一个fru数组来记录内存中页被访问的次数。
初始化为-1,保证这些位置能够马上被填充上。
发生页错误时,只需要在fru数组中找出最小的值,然后返回其下标,并把对应位置成1。
每次发生命中时,需要把命中页对应的fru加1。
即提高其使用频率。
数据结构及核心函数:
#defineINI10000
#definePAGENUM20//内存页数
intcomm[2048];
classCreateReq
{
public:
CreateReq();
intproduceNum(intnum);
};
intCreateReq:
:
produceNum(intnum)
{
returnrand()%num;
}
CreateReq:
:
CreateReq()
{
srand(unsigned(time(0)));
for(inti=0;i<=511;i++){
intm=produceNum(1024);
comm[i*4]=m+1;
intm1=produceNum(m+2);
comm[i*4+1]=m1;
comm[i*4+2]=m1+1;
comm[i*4+3]=produceNum(2047-m1-2+1)+m1+2;
}
for(inti=0;i<=2047;i++)
comm[i]=comm[i]/64;
}
classcontrol
{
private:
intfru[PAGENUM];
intuseTime[PAGENUM];
intage[PAGENUM];
intmemBest[PAGENUM];
intmemFifo[PAGENUM];
intmemLru[PAGENUM];
intmemLfu[PAGENUM];
floatpfBest;
floatpfFifo;
floatpfLru;
floatpfLfu;
floatrateBest;
floatrateFifo;
floatrateLru;
floatrateLfu;
public:
control(void)
{
pfBest=0;
pfFifo=0;
pfLru=0;