请求页式存储管理的页面置换算法实验报告

学生姓名: 学 号: 专业班级:
实验类型:□√ 验证 □ 综合 □ 设计 □ 创新 实验日期: 实验成绩:

一、 实验项目名称
请求页式存储管理的页面置换算法

二、 实验目的
存储管理的主要功能之一是合理地分配空间。请求页式管理是一种常用的虚拟存储管理技术。
本实验的目的是通过请求页式存储管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。

三、 请求页式存储管理的实现原理
1.通过随机数产生一个指令序列,共 320 条指令,指令的地址按下述原则生产:
50%的指令是顺序执行的;
25%的指令是均匀分布在前地址部分;
25%的指令是均匀分布在后地址部分。
2.将指令序列变换成为页地址流
设页面大小为 1K;用户内存容量为 4 页到 32 页;用户虚存容量为 32K。
在用户虚存中,按每 K 存放 10 条指令排列虚存地址,即 320 条指令在虚存中的存放方式
为:第 0 条至第 9 条指令为第 0 页;第 10 条至 19 条指令为第 1 页;…第 310 条至 319 条指
令为第 31 页。
3.计算并输出下述各种算法在不同内存容量下的命中率。
(1) 先进先出算法(FIFO)
(2) 最近最少使用算法(LRU)
(3) 最佳使用算(OPT)
命中率=1-页面失效次数/页地址流长度
本实验中,页地址流长度为 320,页面失效次数为每次访问相应指令时,该指令所
对应的页不在内存的次数。

四、 主要程序代码

#include  
#include 
#include 
#include 
#include 
#define Myprintf printf("|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|\n") /*表格控制*/  
#define bsize 4     //物理块大小 
#define psize 16     //进程大小 

typedef struct page  
{  
       int num;  /*记录页面号*/  
       int time;  /*记录调入内存时间*/  
}Page;                   /* 页面逻辑结构,结构为方便算法实现设计*/  
Page b[bsize];            /*内存单元数*/  
int c[bsize][psize];   /*暂保存内存当前的状态:缓冲区*/  
int queue[100];      /*记录调入队列*/  
int K;             /*调入队列计数变量*/  
int phb[bsize]={0};   //物理块标号 
int pro[psize]={0};   //进程序列号 
int flag[bsize] = {0};  //进程等待次数(存放最久未被使用的进程标志) 
int i = 0, j = 0,k = 0;   //i 表示进程序列号,j 表示物理块号 
int m = -1, n = -1;       //物理块空闲和进程是否相同判断标志 
int max = -1,maxflag = 0; //标记替换物理块进程下标 
int count = 0;            //统计页面缺页次数 
 
//**************************************************************// 
//**************************************************************//随机产生序列号函数 
//************************************************************** 
int* build() 
{ 
 printf("随机产生一个进程序列号为:\n"); 
 int i = 0; 
    srand ( time(NULL) ); 
    for(i=0; i<psize; i++) 
    { 
  pro[i] = 10*rand()/(RAND_MAX+1)+1; 
        printf("%d  ",pro[i]); 
     } 
     printf("\n"); 
  return(pro); 
} 
//**************************************************************//查找空闲物理块 
//************************************************************** 
int searchpb() 
{ 
 for(j=0; j<bsize; j++) 
    { 
  if(phb[j] == 0) 
        { 
           m = j;  
     return m;      
           break; 
        }  
 } 
 return -1; 
} 
//**************************************************************//查找相同进程 
//************************************************************** 
int searchpro() 
{ 
 for(j = 0; j < bsize; j++) 
    { 
       if(phb[j] == pro[i]) 
       { 
          n = j; 
    return j; 
       } 
    } 
 return -1; 
} 
//**************************************************************//初始化内存 
//************************************************************** 
void empty() 
{ 
 for(i=0;i<bsize;i++) 
  phb[i]=0; 
    count=0;                //计数器置零 
} 
//**************************************************************//先进先出页面置换算法 
//************************************************************** 
void FIFO() 
{    
    for(i = 0; i<psize; i++) 
    {        
    m=searchpb(); 
    n=searchpro(); 
  //找 flag 值最大的 
        for(j = 0; j < bsize;j++) 
        { 
           if(flag[j]>maxflag) 
             { 
                 maxflag = flag[j]; 
                 max = j; 
             } 
        }    
        if(n == -1)               //不存在相同进程 
  { 
           if(m != -1)            //存在空闲物理块 
           { 
      phb[m] = pro[i];   //进程号填入该空闲物理块 
      count++; 
               flag[m] = 0; 
               for(j = 0;j <= m; j++) 
               { 
                  flag[j]++; 
               } 
               m = -1; 
           } 
           else                //不存在空闲物理块 
           { 
              phb[max] = pro[i]; 
              flag[max] = 0; 
              for(j = 0;j < bsize; j++) 
              { 
                 flag[j]++; 
              } 
              max = -1; 
              maxflag = 0; 
              count++; 
           } 
       } 
       else                    //存在相同的进程 
       { 
     phb[n] = pro[i]; 
           for(j = 0;j < bsize; j++) 
           { 
      flag[j]++; 
           } 
           n = -1; 
       } 
       for(j = 0 ;j < bsize; j++) 
       { 
     printf("%d  ",phb[j]); 
       } 
       printf("\n"); 
    } 
    printf("缺页次数为:%d\n",count); 
 printf("\n"); 
} 
//************************************************************** 
//************************************************************** 
/*初始化内存单元、缓冲区*/  
void Init(Page *b,int c[bsize][psize])  
{  
       int i,j;  
       for(i=0;i<psize;i++)  
       {  
              b[i].num=-1;  
              b[i].time=psize-i-1;  
       }  
       for(i=0;i<bsize;i++)  
              for(j=0;j<psize;j++)  
                     c[i][j]=-1;  
}  
/*取得在内存中停留最久的页面,默认状态下为最早调入的页面*/  
int GetMax(Page *b)  
{  
       int i;  
       int max=-1; 
       int tag=0; 
       for(i=0;i<bsize;i++)  
       {  
              if(b[i].time>max)  
              {  
                     max=b[i].time;  
                     tag=i;  
              }  
       }  
       return tag;  
} 
/*判断页面是否已在内存中*/  
int   Equation(int fold,Page *b)  
{  
       int i;  
       for(i=0;i<bsize;i++)  
       {  
              if (fold==b[i].num)  
                     return i;  
       }  
       return -1;  
}  
/*LRU 核心部分*/  
void Lruu(int fold,Page *b)  
{  
       int i;  
       int val;  
       val=Equation(fold,b);  
       if (val>=0)  
       {  
              b[val].time=0;  
              for(i=0;i<bsize;i++)  
                     if (i!=val)  
                            b[i].time++;  
       }  
       else  
       {  
              queue[++K]=fold;/*记录调入页面*/  
              val=GetMax(b);  
              b[val].num=fold;  
              b[val].time=0;  
              for(i=0;i<bsize;i++)  
                     if (i!=val)  
                            b[i].time++;  
       }  
} 
void LRU() 
{  
       int i,j;  
       K=-1;  
       Init(b, c);  
       for(i=0;i<psize;i++)  
       {  
              Lruu(pro[i],b);  
              c[0][i]=pro[i];  
              /*记录当前的内存单元中的页面*/  
              for(j=0;j<bsize;j++)  
                     c[j][i]=b[j].num;  
       }  
       /*结果输出*/  
       printf("内存状态为:\n");  
       Myprintf;  
       for(j=0;j<psize;j++)  
              printf("|%2d ",pro[j]);  
       printf("|\n");  
       Myprintf;  
       for(i=0;i<bsize;i++)  
       {     for(j=0;j<psize;j++)  
              {  
              if(c[i][j]==-1)  
                    printf("|%2c ",32);  
              else  
                     printf("|%2d ",c[i][j]);  
              }  
              printf("|\n");  
       }  
       Myprintf;  
       printf("\n 调入队列为:");  
       for(i=0;i<K+1;i++)  
     printf("%3d",queue[i]);  
       printf("\n 缺页次数为:%6d\n 缺页率:%16.6f",K+1,(float)(K+1)/psize);  
 
} 
 
//**************************************************************//主函数 
//************************************************************** 
void main() 
{ 
 int sel ;  
     do{  
     printf("\t\t\t--------------------------------------\t\t\t\n"); 
  printf("\t\t\t ☆☆^-^欢迎进入操作系统界面^-^☆☆  \t\t\t\n"); 
  printf("\t\t\t--------------------------------------\t\t\t\n"); 
  printf("\t\t\t☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\t\t\t\n"); 
     printf("\t\t\t☆            虚拟内存            ☆  \t\t\t\n"); 
  printf("\t\t\t☆--------------------------------☆\t\t\t\n"); 
     printf("\t\t\t☆       1、产生随机序列          ☆  \t\t\t\n"); 
  printf("\t\t\t☆--------------------------------☆\t\t\t\n"); 
     printf("\t\t\t☆       2、最久未使用(LRU)       ☆  \t\t\t\n"); 
  printf("\t\t\t☆--------------------------------☆\t\t\t\n"); 
     printf("\t\t\t☆       3、先进先出(FIFO)        ☆  \t\t\t\n"); 
  printf("\t\t\t☆--------------------------------☆\t\t\t\n"); 
     printf("\t\t\t☆       4、最佳置换算法(OPT)     ☆  \t\t\t\n"); 
  printf("\t\t\t☆--------------------------------☆\t\t\t\n"); 
  printf("\t\t\t☆       5、三种算法的比较()      ☆  \t\t\t\n"); 
  printf("\t\t\t☆--------------------------------☆\t\t\t\n"); 
  printf("\t\t\t☆       0、退出(Exit)            ☆  \t\t\t\n"); 
     printf("\t\t\t☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\t\t\t\n"); 
     printf("请选择所要执行的操作(0/1/2/3/4/5):"); 
     scanf("%d",&sel); 
     switch(sel) 
  { 
    case0:printf("\t\t\t^-^再见!^-^ \t\t\t\n");system("pause");break; 
    case 1:build();break; 
    case 2:printf("最久未使用算\n");LRU();empty();printf("\n");break; 
    case 3:printf("先进先出算\n");FIFO();empty();printf("\n");break; 
    case 5:printf("先进先出算法\n");FIFO();empty(); 
printf("最久未使用算法\n");LRU();empty();break; 
          default: printf("请输入正确的选项号!");printf("\n\n");break; 
  } 
 }while(sel!=0); 
} 

五、 实验数据

1、产生的随机序列:
2 8 2 5 2 4 6 3 1 8 4 9 2 7 2 4

2、 最近最少使用算法(LRU)执行结果
内存状态为:
|—±–±--±–±--±–±--±–±--±–±--±–±--±–±--±–±--|
| 2 | 8 | 2 | 5 | 2 | 4 | 6 | 3 | 1 | 8 | 4 | 9 | 2 | 7 | 2 | 4 |
|—±–±--±–±--±–±--±–±--±–±--±–±--±–±--±–±--|
| 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 2 | 2 | 2 | 2 |
| | 8 | 8 | 8 | 8 | 8 | 6 | 6 | 6 | 6 | 4 | 4 | 4 | 4 | 4 | 4 |
| | | | 5 | 5 | 5 | 5 | 3 | 3 | 3 | 3 | 9 | 9 | 9 | 9 | 9 |
| | | | | | 4 | 4 | 4 | 4 | 8 | 8 | 8 | 8 | 7 | 7 | 7 |
|—±–±--±–±--±–±--±–±--±–±--±–±--±–±--±–±--|

调入队列为: 2 8 5 4 6 3 1 8 4 9 2 7
缺页次数为: 12
缺页率: 0.750000

3、先进先出 FIFO 算法执行结果
2 0 0 0
2 8 0 0
2 8 0 0
2 8 5 0
2 8 5 0
2 8 5 4
6 8 5 4
6 3 5 4
6 3 1 4
6 3 1 8
4 3 1 8
4 9 1 8
4 9 2 8
4 9 2 7
4 9 2 7
4 9 2 7
缺页次数为:12

4、 写出这三种页面置换算法的实现思想
FIFO算法总是淘汰最先调入主存的页面,即淘汰在主存中驻留时间最长的页面,认为驻留时间最长的页不再使用的可能性较大。
LRU算法淘汰的页面是最近一段时间内最久未被访问的那一页,它是基于程序局部性原理来考虑的,认为那些刚被使用过的页面可能还要立即被使用,而那些在较长时间内未被使用的页面可能不会立即使用。
OPT算法,当要调入一页而必须淘汰旧页时,应该淘汰以后不再访问的页,或距现在最长时间后要访问的页面。
5、 对不同算法的性能进行评价
随着页数的增多, FIFO大部分情况和LRU 算法、OPT 算法都是缺页率减小。
OPT 是理想情况,效率是最高的。当然当不缺页时,所有的算法缺页次数都是把所有页调进去的次数。 LRU 算法有时候和FIFO 算法的效率差别并不大。甚至有时候它还比FIFO 低一些的。
此外:
FIFO算法较易实现,对具有线性顺序特征的程序比较适用,而对具有其他特征的程序则效率不高,此算法还可能出现抖动现象(Belady)异常。LRU算法基于程序的局部性原理,所以适用用大多数程序,此算实现必须维护一个特殊的队列——页面淘汰队列。OPT算法虽然产生的缺页数最少,然而,却需要预测程序的页面引用串,这是无法预知的,不可能对程序的运行过程做出精确的断言,不过此理论算法可用做衡量各种具体算法的标准。

你可能感兴趣的:(作业,c)