广州大学操作系统实验三 内存管理
一、实验目的
1、了解虚拟存储技术的特点,掌握虚拟存储请求页式存储管理中几种基本页面置换算法的基本思想和实现过程,并比较它们的效率。
2、了解程序设计技术和内存泄露的原因
二、 实验内容
1、模拟实现请求页式存储管理的几种基本页面置换算法(1)最佳淘汰算法(OPT)(2)先进先出的算法(FIFO)(3)最近最久未使用算法(LRU))
三、 实验要求
(1)通过随机数产生一个指令序列,共320条指令。指令的地址按下述原则生成:A:50%的指令是顺序执行的B:25%的指令是均匀分布在前地址部分C:25%的指令是均匀分布在后地址部分具体的实施方法是:A:在[0,319]的指令地址之间随机选取一起点mB:顺序执行一条指令,即执行地址为m+1的指令C:在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为m’D:顺序执行一条指令,其地址为m’+1E:在后地址[m’+2,319]中随机选取一条指令并执行F:重复步骤A-E,直到320次指令(2)将指令序列变换为页地址流设:页面大小为1K;用户内存容量4页到32页;用户虚存容量为32K。在用户虚存中,按每K存放10条指令排列虚存地址,即320条指令在虚存中的存放方式为:第 0 条-第 9 条指令为第0页(对应虚存地址为[0,9])第10条-第19条指令为第1页(对应虚存地址为[10,19])………………………………第310条-第319条指令为第31页(对应虚存地址为[310,319])按以上方式,用户指令可组成32页。
四、三种置换算法原理
页面置换算法的分类
1.最佳置换算法(OPT)
(1)实现原理:每次选择未来长时间不被访问的或者以后永不使用的页面进行淘汰。
(2)举例:假定系统为某进程分配了三块物理块,并有以下页面: 7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1 程序运行时,先将7,0,1三个页面装入内存。之后,当进程要访问页面2的时候,将会产生缺页中断。此时根据最佳置换算法,因为页面7要在第18次才能访问,页面0在第5次访问,页面1在第14次访问,页面7最久不被使用,所以将页面7淘汰;当进程0要访问时,因为它已存在在内存所以不必产生缺页中断;当页面3要访问时,又引起缺页中断淘汰1;依次类推直到最后一个页面访问完。下图为采用最佳置换算法的置换图。由图可得,采用最佳置换算法发生了6次缺页中断。
(3)特点 缺点:最佳置换算法是一种理想化算法,具有较好的性能,但是实际上无法实现(无法预知一个进程中的若干页面哪一个最长时间不被访问);优点:最佳置换算法可以保证获得最低的缺页率
2 先进先出页面置换算法(FIFO)
(1)实现原理:淘汰最先进入内存的页面,即选择在页面待的时间最长的页面淘汰。
(2)举例 依旧是上一个算法的例子 程序运行时,先将7,0,1三个页面装入内存。之后,当进程要访问页面2的时候,将会产生缺页中断。此时根据先进先出置换算法,因为页面7是最先进入内存的,所以将页面7换出;当进程0要访问时,因为它已存在在内存所以不必产生缺页中断;在进程要访问页面3的时候,因为页面0是最早进入内存的,所以将页面0换出;依次类推直到最后一个页面访问完。下图为采用先进先出置换算法的置换图。由图可得,采用最佳置换算法发生了12次缺页中断。先进先出的页面置换比最佳置换算法的页面置换正好多了一倍;
(3)特点 优点:先进先出算法实现简单,是最直观的一个算法缺点:先进先出的性能最差,因为与通常页面的使用规则不符合,所以实际应用少
3 最近最久未使用置换算法(LRU)
(1)实现原理:选择最近且最久未被使用的页面进行淘汰
(2)举例: 依旧是上一个算法的例子 程序运行时,先将7,0,1三个页面装入内存。之后,当进程要访问页面2的时候,将会产生缺页中断。此时根据最近最久未使用置换算法,因为页面7是最近最久未被使用的的,所以将页面7淘汰;当进程0要访问时,因为它已存在在内存所以不必产生缺页中断;在进程要访问页面3的时候,因为页面1是最近最久未被使用的,所以将页面1淘汰;依次类推直到最后一个页面访问完。下图为采用最近最久未使用的置换算法的置换图。由图可得,采用最近最久未使用置换算法发生了9次缺页中断。
(3)特点 优点:由于考虑程序访问的时间局部性,一般能有较好的性能;实际应用多缺点:实现需要较多的硬件支持,会增加硬件成本
代码:
#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 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("中断!\n");
memory[j]=page[i];
overflow++;
break;
}
if(full==1&&memory[j]==page[i]){
printf("\n\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);
}
printf("步骤 %3d: 需要页面:%3d 结果: ",i,page[i]);
for(j=0;j<frameNum;j++){
printf("|%2d| ",memory[j]);
}
printf("\n");
}
printf("\n命中率为 %f\n",overflow*1.0/TOTALNUM );
}
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++;
}
}
void OPT(int station,int frameNum,int* overflow){
int j,k;
int flag=-1;
printf("\n中断!(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;
}
void FIFO(int station,int framNum,int* overflow){
printf("\n中断!(FIFO)\n");
int m = *overflow%framNum;
memory[m]=page[station];
*overflow+=1;
}
void LRU(int station,int framNum,int* overflow){
printf("\n中断!(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;
}
int main(){
int i;
int mode;//选择要执行的算法
int frameNum=-1;
srand((unsigned)time(NULL));//随机数播种
creatInstruction(0,TOTALNUM);
printf("段数和页数:\n");
for(i=1;i<=TOTALNUM;i++){
printf("%3d.段:%4d 页:%3d |\t",i,instruction[i-1],page[i-1]);
if(i%3==0)
printf("\n");
}
printf("\n==================================================================================\n");
printf("*\n");
printf("选择执行的算法: (0:OPT\t1:FIFO\t2:LRU\t3:LRF\t-1:退出)\n");
printf("调用页面: (1~20)\n*\n");
printf("==================================================================================\n");
printf("请输入要调用的页面:\n");
scanf("%d",&frameNum);
while(frameNum>20||frameNum<=0){
printf("输入有误,请重新尝试!\n");
scanf("%d",&frameNum);
}
while(mode!=-1){
printf("选择要执行的算法:\n");
scanf("%d",&mode);
switch (mode)
{
case -1:
printf("退出!\n");
break;
case 0:
printf("============运行OPT============\n");
replaceArithmatic(frameNum,0);
break;
case 1:
printf("============运行 FIFO===========\n");
replaceArithmatic(frameNum,1);
break;
case 2:
printf("============运行 LRU============\n");
replaceArithmatic(frameNum,2);
break;
default:
printf("输入有误!\n");
break;
}
}
}