LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1460|回复: 5

linux存储管理的常用算法,及其验证(献给正在学操作系统的同学们~~)

[复制链接]
发表于 2005-5-9 21:43:51 | 显示全部楼层 |阅读模式
一、虚拟存储系统
LINUX中,为了提高内存利用率,提供了内外存进程对换机制;内存空间的分配和回收均以页为单位进行;一个进程只需将其一部分(段或页)调入内存便可运行;还支持请求调页的存储管理方式。
当进程在运行中需要访问某部分程序和数据时,发现其所在页面不在内存,就立即提出请求(向CPU发出缺中断),由系统将其所需页面调入内存。这种页面调入方式叫请求调页。
为实现请求调页,核心配置了四种数据结构:页表、页框号、访问位、修改位、有效位、保护位等。
二、页面置换算法
当CPU接收到缺页中断信号,中断处理程序先保存现场,分析中断原因,转入缺页中断处理程序。该程序通过查找页表,得到该页所在外存的物理块号。如果此时内存未满,能容纳新页,则启动磁盘I/O将所缺之页调入内存,然后修改页表。如果内存已满,则须按某种置换算法从内存中选出一页准备换出,是否重新写盘由页表的修改位决定,然后将缺页调入,修改页表。利用修改后的页表,去形成所要访问数据的物理地址,再去访问内存数据。整个页面的调入过程对用户是透明的。
常用的页面置换算法有
1、最佳置换算法(Optimal)
2、先进先出法(Fisrt In First Out)
3、最近最久未使用(Least Recently Used)
4、最不经常使用法(Least Frequently Used)
5、最近未使用法(No Used Recently)
三、参考程序:
[php]#define TRUE 1
#define FALSE 0
#define INVALID -1
#define NULL  0

#define  total_instruction  320     /*指令流长*/
#define  total_vp  32               /*虚页长*/
#define  clear_period  50           /*清0周期*/

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 struct pfc_struct pfc_type;

pfc_type pfc[total_vp],*freepf_head,*busypf_head,*busypf_tail;

int diseffect,  a[total_instruction];
int page[total_instruction],  offset[total_instruction];

int  initialize(int);
int  FIFO(int);
int  LRU(int);
int  LFU(int);
int  NUR(int);
int  OPT(int);

int main( )
{
  int s,i,j;
  srand(10*getpid());              /*由于每次运行时进程号不同,故可用来作为初始化随机数队列的“种子”*/
s=(float)319*rand( )/32767/32767/2+1;  //
for(i=0;i<total_instruction;i+=4) /*产生指令队列*/
{
     if(s<0||s>319)
     {
       printf("When i==%d,Error,s==%d\n",i,s);
       exit(0);
     }
     a=s;                            /*任选一指令访问点m*/
     a[i+1]=a+1;                     /*顺序执行一条指令*/
     a[i+2]=(float)a*rand( )/32767/32767/2; /*执行前地址指令m' */
     a[i+3]=a[i+2]+1;                   /*顺序执行一条指令*/

     s=(float)(318-a[i+2])*rand( )/32767/32767/2+a[i+2]+2;
     if((a[i+2]>318)||(s>319))
       printf("a[%d+2],a number which is :%d and s==%d\n",i,a[i+2],s);

}
for (i=0;i<total_instruction;i++) /*将指令序列变换成页地址流*/
{
     page=a/10;
     offset=a%10;
}
for(i=4;i<=32;i++)   /*用户内存工作区从4个页面到32个页面*/
{
      printf("---%2d page frames---\n",i);
      FIFO(i);
      LRU(i);
      LFU(i);
      NUR(i);
      OPT(i);

}
   return 0;
}

int initialize(total_pf)              /*初始化相关数据结构*/
int total_pf;                          /*用户进程的内存页面数*/
{int i;
diseffect=0;
for(i=0;i<total_vp;i++)
{
       pl.pn=i;
       pl.pfn=INVALID;        /*置页面控制结构中的页号,页面为空*/
       pl.counter=0;
       pl.time=-1;         /*页面控制结构中的访问次数为0,时间为-1*/
}
for(i=0;i<total_pf-1;i++)
{
       pfc.next=&pfc[i+1];
       pfc.pfn=i;
}   /*建立pfc[i-1]和pfc之间的链接*/
pfc[total_pf-1].next=NULL;
pfc[total_pf-1].pfn=total_pf-1;
freepf_head=&pfc[0];         /*空页面队列的头指针为pfc[0]*/

return 0;
}


int FIFO(total_pf)              /*先进先出算法*/
int total_pf;                    /*用户进程的内存页面数*/
{
     int i,j;
     pfc_type *p;
     initialize(total_pf);         /*初始化相关页面控制用数据结构*/
     busypf_head=busypf_tail=NULL; /*忙页面队列头,队列尾链接*/
     for(i=0;i<total_instruction;i++)
   {
   if(pl[page].pfn==INVALID)   /*页面失效*/
     {
      diseffect+=1;                  /*失效次数*/
      if(freepf_head==NULL)         /*无空闲页面*/
       {
         p=busypf_head->next;
         pl[busypf_head->pn].pfn=INVALID;
         freepf_head=busypf_head;  /*释放忙页面队列的第一个页面*/
         freepf_head->next=NULL;
         busypf_head=p;
       }
        p=freepf_head->next;         /*按FIFO方式调新页面入内存页面*/
        freepf_head->next=NULL;
        freepf_head->pn=page;
        pl[page].pfn=freepf_head->pfn;

        if(busypf_tail==NULL)
        busypf_head=busypf_tail=freepf_head;
     else
    {
      busypf_tail->next=freepf_head;  /*free页面减少一个*/
      busypf_tail=freepf_head;
     }
        freepf_head=p;
     }
}
printf("FIFO:%6.4f\n",1-(float)diseffect/320);

return 0;
}

int LRU (total_pf)       /*最近最久未使用算法*/
int total_pf;
{
int min,minj,i,j,present_time;
initialize(total_pf);
present_time=0;

for(i=0;i<total_instruction;i++)
  {
      if(pl[page].pfn==INVALID)             /*页面失效*/
    {
         diseffect++;
         if(freepf_head==NULL)              /*无空闲页面*/
      {
         min=32767;
         for(j=0;j<total_vp;j++)            /*找出time的最小值*/
           if(min>pl[j].time&&pl[j].pfn!=INVALID)
                    {
                      min=pl[j].time;
                      minj=j;
                     }
          freepf_head=&pfc[pl[minj].pfn];   //腾出一个单元
          pl[minj].pfn=INVALID;
          pl[minj].time=-1;
          freepf_head->next=NULL;
      }
        pl[page].pfn=freepf_head->pfn;   //有空闲页面,改为有效
        pl[page].time=present_time;
        freepf_head=freepf_head->next;      //减少一个free 页面
     }
    else
       pl[page].time=present_time;        //命中则增加该单元的访问次数

    present_time++;
   }
printf("LRU:%6.4f\n",1-(float)diseffect/320);
return 0;
}

int NUR(total_pf)                  /*最近未使用算法*/
int  total_pf;
{ int i,j,dp,cont_flag,old_dp;
pfc_type *t;
initialize(total_pf);
dp=0;
for(i=0;i<total_instruction;i++)
{ if (pl[page].pfn==INVALID)         /*页面失效*/
     {diseffect++;
      if(freepf_head==NULL)               /*无空闲页面*/
         { cont_flag=TRUE;
           old_dp=dp;
           while(cont_flag)
             if(pl[dp].counter==0&&pl[dp].pfn!=INVALID)
                 cont_flag=FALSE;
             else
            {
             dp++;
             if(dp==total_vp)
                dp=0;
             if(dp==old_dp)
                for(j=0;j<total_vp;j++)
                   pl[j].counter=0;
             }
           freepf_head=&pfc[pl[dp].pfn];
           pl[dp].pfn=INVALID;
           freepf_head->next=NULL;
         }
           pl[page].pfn=freepf_head->pfn;
           freepf_head=freepf_head->next;
      }
else
     pl[page].counter=1;
     if(i%clear_period==0)
        for(j=0;j<total_vp;j++)
             pl[j].counter=0;
}
printf("NUR:%6.4f\n",1-(float)diseffect/320);

return 0;
}

int OPT(total_pf)       /*最佳置换算法*/
int total_pf;
{int i,j, max,maxpage,d,dist[total_vp];
pfc_type *t;
initialize(total_pf);
for(i=0;i<total_instruction;i++)
{ //printf("In OPT for 1,i=%d\n",i);  //i=86;i=176;206;250;220,221;192,193,194;258;274,275,276,277,278;
  if(pl[page].pfn==INVALID)      /*页面失效*/
   {
      diseffect++;
      if(freepf_head==NULL)         /*无空闲页面*/
         {for(j=0;j<total_vp;j++)
               if(pl[j].pfn!=INVALID) dist[j]=32767;  /* 最大"距离" */
               else dist[j]=0;
          d=1;
          for(j=i+1;j<total_instruction;j++)
            {
             if(pl[page[j]].pfn!=INVALID)
             dist[page[j]]=d;
             d++;
             }
          max=-1;
          for(j=0;j<total_vp;j++)
          if(max<dist[j])
            {
              max=dist[j];
              maxpage=j;
             }
           freepf_head=&pfc[pl[maxpage].pfn];
           freepf_head->next=NULL;
           pl[maxpage].pfn=INVALID;
          }
   pl[page].pfn=freepf_head->pfn;
   freepf_head=freepf_head->next;
     }
}
printf("OPT:%6.4f\n",1-(float)diseffect/320);

return 0;
}

int  LFU(total_pf)        /*最不经常使用置换法*/
int total_pf;
{
int i,j,min,minpage;
pfc_type *t;
initialize(total_pf);
for(i=0;i<total_instruction;i++)
    {  if(pl[page].pfn==INVALID)      /*页面失效*/
        { diseffect++;
          if(freepf_head==NULL)          /*无空闲页面*/
           { min=32767;
            for(j=0;j<total_vp;j++)
              {if(min>pl[j].counter&&pl[j].pfn!=INVALID)
                  {
                   min=pl[j].counter;
                   minpage=j;
                  }
               pl[j].counter=0;
               }
            freepf_head=&pfc[pl[minpage].pfn];
            pl[minpage].pfn=INVALID;
            freepf_head->next=NULL;
            }
           pl[page].pfn=freepf_head->pfn;   //有空闲页面,改为有效
           pl[page].counter++;
           freepf_head=freepf_head->next;      //减少一个free 页面
        }
        else
           pl[page].counter++;

      }
printf("LFU:%6.4f\n",1-(float)diseffect/320);

return 0;
}[/php]

四、运行结果
4 page frams
FIFO: 0.7312
LRU: 0.7094
LFU: 0.5531
NUR: 0.7688
OPT: 0.9750
5 page frams
   …………
五、分析
1、从几种算法的命中率看,OPT最高,其次为NUR相对较高,而FIFO与LRU相差无几,最低的是LFU。但每个页面执行结果会有所不同。
2、OPT算法在执行过程中可能会发生错误
发表于 2005-5-9 23:07:16 | 显示全部楼层
把标题改改吧。不然查找起来不方便。
回复 支持 反对

使用道具 举报

发表于 2005-5-9 23:09:43 | 显示全部楼层
不错!
问一下,OPT算法是什么?好像是一个无法实现的页面置换算法吧?
回复 支持 反对

使用道具 举报

发表于 2005-5-9 23:15:50 | 显示全部楼层
记得是仅有理论意义的算法。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-5-10 10:40:54 | 显示全部楼层
OPT算法是一种理想情况下的页面置换算法,要点是选择以后不需要或最迟的将来才需要的页面完成置换。
又叫最优淘汰算法,发这个贴主要是想引出高人重点给讲讲算法,我还处于理论阶段,学生,好多东西不理解
回复 支持 反对

使用道具 举报

发表于 2005-5-10 10:45:02 | 显示全部楼层
盛赞rwimn!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表