操作系统页面置换算法命中率比较

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>    //在window操作系统下要屏蔽此条指令

#include <string.h>

#ifndef _UNISTD_H

#define _UNISTD_H

#include <IO.H>

#include <PROCESS.H>

#endif

#define TRUE 1

#define FALSE 0

#define INVALID -1

#define total_instruction  320     //指令流长

#define total_vp  32               //虚页长

#define clear_period  50           //清周期

 

typedef struct                      //页面结构

{

   int pn,                               //页面序号

         pfn,                        //页面所在内存区的帧号

         counter,                    //单位时间内访问次数

         time;                            //上次访问的时间

}pl_type;

pl_type pl[total_vp];               //页面结构数组

 

struct pfc_struct{                  //页面控制结构

    int pn,                         //页面号

          pfn;                            //内存区页面的帧号

    struct pfc_struct *next;        //页面指针,用于维护内存缓冲区的链式结构

};

typedef structpfc_struct pfc_type;  //主存区页面控制结构别名

pfc_type pfc[total_vp],               //主存区页面控制结构数组

*freepf_head,                         //主存区页面控制结构的空闲页面头指针

*busypf_head,                         //主存区页面控制结构的忙页面头指针

*busypf_tail;                         //主存区页面控制结构的忙页面尾指针

int diseffect;                             //页错误计数器,初次把页面载入主存时也当做页错误

int a[total_instruction];             //随即指令流数组

int page[total_instruction];          //指令对应的页面号

int offset[total_instruction];        //指令所在页面中的偏移量

 

int initialize(int);                //初始化页面结构数组和页面控制结构数组

int FIFO(int);                           //先进先出算法

int LRU(int);                            //最近最久未使用算法

int OPT(int);                            //最佳置换算法

int CLOCK(int);                     //简单时钟(钟表)算法

 

 

int main( )

{

   int s;         //随机数

     int  i;

   srand(10*getpid()); /*每次运行时进程号不同,用来作为初始化随机数队列的"种子"*/

   s = (int)((float)(total_instruction-1)*(rand()/(RAND_MAX+1.0)));

     printf("\n------------随机产生指令流------------\n");

   for (i=0; i<total_instruction; i+=4) //产生指令队列

   {

       a[i]=s; //任选一指令访问点m

       a[i+1]=a[i]+1; //顺序执行一条指令

       a[i+2]=(int)((float)a[i]*(rand()/(RAND_MAX+1.0)));//执行前地址指令m'

       a[i+3]=a[i+2]+1; //顺序执行一条指令

       printf("%6d%6d%6d%6d\n",a[i],a[i+1],a[i+2],a[i+3]);

       s  = (int)((float)((total_instruction-1)-a[i+2])*(rand()/(RAND_MAX+1.0)))+ a[i+2];

   }

     printf("--------------------------------------\n");

     for (i=0;i<total_instruction;i++) //将指令序列变换成页地址流

   {

       page[i]=a[i]/10;

       offset[i]=a[i]%10;

   }

     printf("\n--不同页面工作区各种替换策略的命中率表--\n");

   printf("Page\t FIFO\t LRU\t OPT\tCLOCK\n");

   for(i=4;i<=32;i++)   //用户内存工作区从个页面到个页面

   {

       printf(" %2d \t",i);

       FIFO(i);

       LRU(i);

        OPT(i);

        CLOCK(i);

       printf("\n");

   }

return 0;

}

 

//初始化页面结构数组和页面控制结构数组

//total_pf;  用户进程的内存页面数

int initialize(inttotal_pf)

{

   int i;

   diseffect=0;

   for(i=0;i<total_vp;i++)

     {

         pl[i].pn=i;

         pl[i].pfn=INVALID;          //置页面所在主存区的帧号为-1.表示该页不在主存中

         pl[i].counter=0;            //置页面结构中的访问次数为

         pl[i].time=-1;                   //置页面结构中的上次访问的时间为-1

     }

     for(i=0;i<total_pf-1;i++)

     {

         pfc[i].next=&pfc[i+1];        //建立pfc[i-1]和pfc[i]之间的链接

         pfc[i].pfn=i;                //初始化主存区页面的帧号

     }

     pfc[total_pf-1].next=NULL;

     pfc[total_pf-1].pfn=total_pf-1;

     freepf_head=&pfc[0];             //主存区页面控制结构的空闲页面头指针指向pfc[0]

     return 0;

}

 

 

 

//最近最久未使用算法

//int total_pf;       用户进程的内存页面数

int LRU (inttotal_pf)

{

   int MinT;                    //最小的访问时间,即很久没被访问过

     int MinPn;                       //拥有最小的访问时间的页的页号

     int i,j;

     int CurrentTime;                               //系统当前时间

   initialize(total_pf);                          //初始化页面结构数组和页面控制结构数组

   CurrentTime=0;

     diseffect=0;

     for(i=0;i<total_instruction;i++)

     {

         if(pl[page[i]].pfn==INVALID)             //页面失效

         {

              diseffect++;                              //页错误次数加

            if(freepf_head==NULL)               //无空闲页面

            {

               MinT=100000;

                 for(j=0;j<total_vp;j++){            //找出time的最小值,表明该页很久没被访问过

                      if(MinT>pl[j].time&&pl[j].pfn!=INVALID)

                      {

                       MinT=pl[j].time;

                       MinPn=j;

                      }

                 }

                 freepf_head=&pfc[pl[MinPn].pfn];   //最久没被访问过的页被释放

                 pl[MinPn].pfn=INVALID;             //最久没被访问过的页被换出主存

                 pl[MinPn].time=-1;                //最久没被访问过的页的访问时间置为无效

                 freepf_head->next=NULL;

              }

           pl[page[i]].pfn=freepf_head->pfn;      //有空闲页面,把相应的页面换入主存,并把pfn改为相应的帧号

            pl[page[i]].time=CurrentTime;          //令访问时间为当前系统时间

           freepf_head=freepf_head->next;       //减少一个空闲页面

         }

         else

              pl[page[i]].time=CurrentTime;        //命中则刷新该单元的访问时间

         CurrentTime++;                           //系统当前时间加

   }

     printf("%6.3f\t",1-(float)diseffect/320);

     return 0;

}

 

 

 

//最佳置换算法

//int total_pf;       用户进程的内存页面数

int OPT(inttotal_pf)

{

     int i,j;

     int MaxD;                        //将来最近一次访问的距离的最大值(以时间单元度量)

     int MaxPn;                           //将来最近一次访问的距离的最大值的页号

     int dis;                         //距离计数器

     int dist[total_vp];                  //距离数组,保存距离上一次访问的时间差距个数

     initialize(total_pf);                //初始化页面结构数组和页面控制结构数组

     diseffect=0;

     for(i=0;i<total_instruction;i++)

     {

         if(pl[page[i]].pfn==INVALID)         //页面失效

         {

              diseffect++;                    //页错误次数加

              if(freepf_head==NULL)            //无空闲页面

              {

                   for(j=0;j<total_vp;j++)

                   {

                       if(pl[j].pfn!=INVALID) //如果该页在主存中

                            dist[j]=100000;        // 该页关联的距离值改为最大值

                       else

                            dist[j]=0;             //如果不在该页主存中,该页关联的距离值改为

                   }

                   dis=1;                           //初始距离值为

                   for(j=i+1;j<total_instruction;j++)  //从要替换的指令的下一条算起,

                   {

                       if(pl[page[j]].pfn!=INVALID&&pl[page[j]].counter==0)   //如果该页在主存中,并且是将要最近访问的页

                       //if(pl[page[j]].pfn!=INVALID &&dist[page[j]]==100000)  //此条语句原理与上相同

                       {    dist[page[j]]=dis;          //距离值改为dis

                            pl[page[j]].counter=1;      //使访问次数标志加,区别第一次访问和第二次访问

                       }

                       dis++;

                   }

                   MaxD=-1;

                   for(j=0;j<total_vp;j++)

                   {

                       pl[j].counter=0;                 //重置访问次数为

                       if(MaxD<dist[j])                 //查找将来最近一次访问的距离的最大值及其序号

                       {

                            MaxD=dist[j];

                            MaxPn=j;

                       }

                  }

                       freepf_head=&pfc[pl[MaxPn].pfn];  //替换将来一段时间最久访问的页

                       freepf_head->next=NULL;

                       pl[MaxPn].pfn=INVALID;

              }

              pl[page[i]].pfn=freepf_head->pfn;    //把当前页换入主存中,并且把当前页的pfn改为换入页的帧号,

              freepf_head=freepf_head->next;        //减少一个空闲页面

         }//if

     }//for

     printf("%6.3f\t",1-(float)diseffect/320);

     return 0;

}

 

//简单时钟算法

//int total_pf;       用户进程的内存页面数

int CLOCK(inttotal_pf)

{

     int i;

     int use[total_vp];           //使用位

     int swap;

     swap=0;             //发生替换

     initialize(total_pf);

     pfc_type*pnext;    //时钟指针

     pfc_type*head;         //队列头指针

     pnext=freepf_head;

     head=freepf_head;

     for(i=0;i<total_vp;i++){use[i]=0;}      //初始化使用位为

     diseffect=0;

     for(i=0;i<total_instruction;i++)

     {

         if (pl[page[i]].pfn==INVALID)         //页面失效,不在主存中

         {

              diseffect++;                         //页错误次数加

              if(freepf_head==NULL)               //无空闲页面

              {

 

                       while(use[pnext->pfn]==1)    //若时钟指针指向的页的使用位为,则改为并跳过

                       {

                            use[pnext->pfn]=0;

                            pnext=pnext->next;

                            if(pnext==NULL) pnext=head; //如果时钟指针到达队列尾部,重新返回头部

                       }

                       //换出被替换的页

                       pl[pnext->pn].pfn=INVALID;

                       swap=1;

              }

              if(use[pnext->pfn]==0){  //如果使用位为,则换入相应的页

                   pl[page[i]].pfn=pnext->pfn;     //页面结构中要标记帧号

                   pnext->pn=page[i];              //页面控制结构中要标记页号

                   use[pnext->pfn]=1;               //重置使用位为

                   pnext=pnext->next;               //时钟指针下移

                   if(pnext==NULL) pnext=head;      //如果时钟指针到达队列尾部,重新返回头部

                   if(swap==0){ freepf_head=freepf_head->next;    }

              }

 

         }else{//页面在主存中

              use[pl[page[i]].pfn]=1;       //刷新使用位为

         }

 

     }

     printf("%6.3f\t",1-(float)diseffect/320);

     return 0;

}

 

 

//先进先出算法版本

//int total_pf;       用户进程的内存页面数

//实现细节由CLOCK算法退化而来,与FIFO同效果

int FIFO(inttotal_pf)

{

     int i;

     int use[total_vp];

     int swap=0;

     initialize(total_pf);

     pfc_type*pnext,*head;

     pnext=freepf_head;

     head=freepf_head;

     for(i=0;i<total_vp;i++){use[i]=0;}

     diseffect=0;

     for(i=0;i<total_instruction;i++)

     {

         if (pl[page[i]].pfn==INVALID)         //页面失效,不在主存中

         {

              diseffect++;

              if(freepf_head==NULL)               //无空闲页面

              {

                   while(use[pnext->pfn]==1)

                   {

                       use[pnext->pfn]=0;

                       pnext=pnext->next;

                       if(pnext==NULL) pnext=head;

                   }

                   //换出被替换的页

                   pl[pnext->pn].pfn=INVALID;

                   swap=1;

              }

              if(use[pnext->pfn]==0){  //如果使用位为,则换入相应的页

                   pl[page[i]].pfn=pnext->pfn;     //页面结构中要标记帧号

                   pnext->pn=page[i];              //页面控制结构中要标记页号

                   use[pnext->pfn]=1;               //重置使用位为

                   pnext=pnext->next;

                   if(pnext==NULL) pnext=head;

                   if(swap==0){ freepf_head=freepf_head->next;    }

              }

         }

     }

     printf("%6.3f\t",1-(float)diseffect/320);

     return 0;

}

 

设计一个虚拟存储区和内存工作区,并使用下列算法计算访问命中率. (1) 进先出的算法(FIFO) (2) 最近最少使用的算法(LRU) (3) 最佳淘汰算法(OPT)(4) 最少访问页面算法(LFU) (5) 最近最不经常使用算法(NUR) 命中率=1-页面失效次数/页地址流长度 本实验的程序设计基本上按照实验内容进行。即首先用 srand()和 rand()函数定 义和产生指令序列,然后将指令序列变换成相应的页地址流,并针对不同的算法 计算出相应的命中率。相关定义如下: 1 数据结构 (1)页面类型 typedef struct{ int pn,pfn,counter,time; }pl-type; 其中 pn 为页号,pfn 为面号, counter 为一个周期内访问该页面的次数, time 为访问时间. (2) 页面控制结构 pfc-struct{ int pn,pfn; struct pfc_struct *next;} typedef struct pfc_struct pfc_type; pfc_type pfc_struct[total_vp],*freepf_head,*busypf_head; pfc_type *busypf_tail; 其中 pfc[total_vp]定义用户进程虚页控制结构, *freepf_head 为空页面头的指针, *busypf_head 为忙页面头的指针, *busypf_tail 为忙页面尾的指针. 2.函数定义 (1)Void initialize( ):初始化函数,给每个相关的页面赋值. (2)Void FIFO( ):计算使用 FIFO 算法时的命中率. (3)Void LRU( ):计算使用 LRU 算法时的命中率. (4)Void OPT( ):计算使用 OPT 算法时的命中率. (5)Void LFU( ):计算使用 LFU 算法时的命中率. (6)Void NUR( ):计算使用 NUR 算法时的命中率. 3.变量定义 (1)int a[total_instruction]: 指令流数据组.(2)int page[total_instruction]: 每条指令所属的页号. (3)int offset[total_instruction]: 每页装入 10 条指令后取模运算页号偏移 值. (4)int total_pf: 用户进程的内存页面数. (5)int disaffect: 页面失效次数.
一、课程设计目的 通过请求页式管理方式中页面置换算法的模拟设计,了解虚拟存储技术的特点,掌握请 求页式存储管理中的页面置换算法。 容 二、课程设计内容 模拟实现 OPT(最佳置换)、FIFO 和 LRU 算法,并计算缺页率。 示 三、要求及提示 本题目必须单人完成。 1、首先用随机数生成函数产生一个“指令将要访问的地址序列”,然后将地址序列变换 成相应的页地址流(即页访问序列),再计算不同算法下的命中率。 2、通过随机数产生一个地址序列,共产生 400 条。其中 50%的地址访问是顺序执行的, 另外 50%就是非顺序执行。且地址在前半部地址空间和后半部地址空间均匀分布。具体产 生方法如下: 1) 在前半部地址空间,即[0,199]中随机选一数 m,记录到地址流数组中(这是 非顺序执行); 2) 接着“顺序执行一条指令”,即执行地址为 m+1 的指令,把 m+1 记录下来; 3) 在后半部地址空间,[200,399]中随机选一数 m’,作为新指令地址; 4) 顺序执行一条指令,其地址为 m’+1; 5) 重复步骤 1~4,直到产生 400 个指令地址。 3、将指令地址流变换成页地址(页号)流,简化假设为: 1) 页面大小为 1K(这里 K 只是表示一个单位,不必是 1024B); 2) 用户虚存容量为 40K; 3) 用户内存容量为 4 个页框到 40 个页框; 6 4) 用户虚存中,每 K 存放 10 条指令,所以那 400 条指令访问地址所对应的页地 址(页号)流为:指令访问地址为[0,9]的地址为第 0 页;指令访问地址为[10, 19]的地址为第 1 页;……。按这种方式,把 400 条指令组织进“40 页”,并 将“要访问的页号序列”记录到页地址流数组中。 4、循环运行,使用户内存容量从 4 页框到 40 页框。计算每个内存容量下不同页面置换 算法命中率。输出结果可以为: 页框数 OPT 缺页率 FIFO 缺页率 LRU 缺页率 [4] OPT:0.5566 FIFO:0.4455 LRU:0.5500 [5] OPT:0.6644 FIFO:0.5544 LRU:0.5588 …… …… …… …… [39] OPT:0.9000 FIFO:0.9000 LRU:0.9000 [40] OPT:1.0000 FIFO:1.0000 LRU:1.0000 注 1:在某一次实验中,可能 FIFO 比 LRU 性能更好,但足够多次的实验表明 LRU 的平均性能比 FIFO 更好。 注 2:计算缺页率时,以页框填满之前和之后的总缺页次数计算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值