zoukankan      html  css  js  c++  java
  • 实验四 主存空间的分配和回收

    1.    目的和要求

    1.1.           实验目的

    用高级语言完成一个主存空间的分配和回收程序,以加深对动态分区分配方式及其算法的理解。

    1.2.           实验要求

    采用连续分配方式之动态分区分配存储管理,使用首次适应算法、循环首次适应算法、最佳适应算法和最坏适应算法4种算法完成设计(任选两种算法)。

    (1)**设计一个作业申请队列以及作业完成后的释放顺序,实现主存的分配和回收。采用分区说明表进行。

    (2)或在程序运行过程,由用户指定申请与释放。

    (3)设计一个空闲区说明表,以保存某时刻主存空间占用情况。把空闲区说明表的变化情况以及各作业的申请、释放情况显示。

    2.    实验内容

    根据指定的实验课题,完成设计、编码和调试工作,完成实验报告

    3.    实验环境

    可以选用Turbo C作为开发环境。也可以选用Windows下的VB,CB或其他可视化环境,利用各种控件较为方便。自主选择实验环境。

    4.    代码如下

      #include "stdio.h"
    #include <stdlib.h>
    #include<string.h>
    #include <conio.h>
    #include "iostream.h"
    #define getjcb(type)  (type*)malloc(sizeof(type))
    #define getsub(type)  (type*)malloc(sizeof(type))
    #define NULL 0
    int num,num2;  //要调度的作业数和要回收的区域数
    int m=0;     //已分配作业数
    int flag;     //分配成功标志
    int isup,isdown;   //回收区域存在上邻和下邻的标志
    int is=0;
    
    struct jcb{
            char name[10];
            char state;
            int ntime; //所需时间
                 int size;  //所需空间大小
                     int addr;  //所分配分区的首地址
            struct jcb *link;
                } *ready =NULL, *p,*q,*as=NULL;
                    //作业队列ready,已分配作业队列as
            typedef struct jcb JCB;
    
    struct subarea{         //分区块
                char name[10];
                int addr;    //分区首地址
            int size;    //分区大小
            char state;
            struct subarea *link;
      } *sub=NULL,*r,*s,*cur;
      //空闲分区队列sub,当前分区指针cur
            typedef struct subarea SUB;
    
    void sort_sub()     /*对空闲分区按从小到大排序*/
    {   SUB *first,*second;
        int insert=0;
        if((sub==NULL)||((s->size)<(sub->size)))   /*插在队列之首*/
        {s->link=sub;
         sub=s;
        }
        else{first=sub;        /*寻找适当的位置插入*/
              second=first->link;
              while(second!=NULL)
              {
                  if((s->size)<(second->size))
                  {
                   s->link=second;
                   first->link=s;
                   second=NULL;
                   insert=1;
                  }
                  else
                  {
                     first=first->link;
                    second=second->link;
                  }
              }
              if(insert==0)first->link=s;   /*插在队尾*/
              }
    } 
    
    void firstsort()     //对空闲分区按从小到大排序sort
    {
     JCB *first;
     if(ready==NULL)  ready=p;
     else{
       first=ready;
       while(first->link!=NULL)
           first=first->link;
       first->link=p;
       p->link=NULL;
      }
    }
    
    
    void lastsort()      //建立对已分配作业队列的排列函数,直接插在队列之尾sort3
    {
     JCB *fir;
     if(as==NULL) as=q;
     else{
       fir=as;
       while(fir->link!=NULL)
         fir=fir->link;
       fir->link=q;
       q->link=NULL;
      }
      m++;
    }
    
    void input() /* 建立作业控制块函数*/
    {
     int i;
     printf("
    请输入要调度的总作业数:");
     scanf("%d",&num);
     for(i=0;i<num;i++)
      {
       printf("
    作业号No.%d:
    ",i);
       p=getjcb(JCB);
       printf("
    输入作业名:");
       scanf("%s",&p->name);
       printf("
    输入作业的大小:");
       scanf("%d",&p->size);
       printf("
    输入作业所需运行时间:");
       scanf("%d",&p->ntime);
       p->state='w';
       p->link=NULL;
       firstsort(); /* 调用sort函数*/
      }
     printf("
     按任一键继续......
    ");
     getch();
    }
    
    void input2()     /*建立要回收区域的函数*/
    {
     JCB *k;
     int has;
     q=getjcb(JCB);
     printf("
    输入区域名(作业名):");
     scanf("%s",&q->name);
     p=as;
     while(p!=NULL)
      {
         if(strcmp(p->name,q->name)==0)  /*在已分配作业队列中寻找*/
           {
            q->addr=p->addr;
            q->size=p->size;
            has=1;    /*输入作业名存在标志位*/
            if(p==as)  as=p->link;    /*在已分配作业队列中删除该作业*/
            else
              {k=as;
               while(k->link!=p)  k=k->link;
               k->link=k->link->link;      /*删除*/
              }
            printf("输出该作业首地址:%d
    ",q->addr);
            printf("输出该作业大小:%d
    
    ",q->size);
            q->link=NULL;
            break;
           }
       else
           {p=p->link; has=0;}   /*输入作业名不存在标志*/
      }
     if(has==0)
      {printf("
    输入作业名错误!请重新输入!
    ");
       input2();
      }  
    }
    
    void init_sub()       /*初始化空闲分区表*/
    {
     r=getsub(SUB);
     strcpy(r->name,"one"); r->addr=5; r->size=10; r->state='n';
     sub=r;
     s=getsub(SUB);
     strcpy(s->name,"two"); s->addr=20; s->size=120; s->state='n';
     sub->link=s;r=s;
     s=getsub(SUB);
     strcpy(s->name,"three"); s->addr=160; s->size=40; s->state='n'; 
     r->link=s;r=s;
     s=getsub(SUB);
     strcpy(s->name,"four"); s->addr=220; s->size=10; s->state='n'; 
     r->link=s;r=s;
     s=getsub(SUB);
     strcpy(s->name,"five"); s->addr=250; s->size=20; s->state='n'; 
     r->link=s;
    }
    
    void disp()    /*空闲分区表的显示函数*/
    {
     printf("		 分区          首地址           长度          状态 
    ");
     r=sub;
     while(r!=NULL)
       {
        printf("		 %s		%d		%d		%c
    ",r->name,r->addr,r->size,r->state);
        r=r->link;
       }
     printf("
    ");
    }
    
    void disp2()   /*显示已分配内存的作业表函数*/
    {
    
     printf("		 作业名         首地址          长度          状态 
    ");
     p=as;
     while(p!=NULL)
       {
        printf("		 %s		%d		%d		%c
    ",p->name,p->addr,p->size,p->state);
        p=p->link;
       }
     printf("
    
    ");
    }
    
    void perfit(JCB *pr) /*最佳适应作业分区assign*/
    {
     SUB *k;
     r=sub;
     while(r!=NULL)
      {
       if(((r->size)>(pr->size))&&(r->state=='n'))   /*有空闲分区大于作业大小的情况*/
          {
           pr->addr=r->addr;
           r->size-=pr->size;
           r->addr+=pr->size;
           if(r==sub) sub=r->link;     /*删除空闲分区*/ 
           else 
             {s=sub;
              while(s->link!=r)  s=s->link;
              s->link=s->link->link;      /*删除空闲分区*/ 
             }
           flag=1;       /*分配成功标志位置1*/
           q=pr;
           lastsort();    /*插入已分配作业队列*/
           //重新插入剩余空闲分区,插在合适位置
          
     if(r->size<sub->size)   /*插入队首*/
             {
              r->link=sub;
              sub=r;
             }
           else   /*插在适当的位置*/
            {
             s=sub;
             while((s->size)<=(r->size))   s=s->link;
             k=sub;
             if(k==s)  {r->link=sub->link; sub=r;}   /*插在队首的后一个位置*/
             else   /*第二个以后的位置*/
              {
               while(k->link!=s)  k=k->link;
               r->link=s;    
               k->link=r;
              }    
             }
             printf("作业%s的分区为[%s],首地址为%d.
    ",p->name,r->name,pr->addr);  
             break;          
          } 
       else if(((r->size)==(pr->size))&&(r->state=='n'))    /*有空闲分区等于作业大小的情况*/
          {
           pr->addr=r->addr;
           flag=1;    /*分配成功标志位置1*/
           q=pr;
           lastsort();         /*插入已分配作业队列*/
           s=sub;        /*空闲分区已完成分配,应删除*/
           while(s->link!=r)  s=s->link;
           s->link=s->link->link;     /*删除空闲分区*/  
           printf("作业%s的分区为[%s],首地址为%d.
    ",p->name,r->name,pr->addr); 
           break;
         }
       else 
             {r=r->link;  flag=0;}
    }
     if(flag==0)           /*作业过大的情况*/
     {
      printf("作业%s长度过大,内存不足,分区分配出错!
    ",p->name);
      is=1;
     }
    }
    
    void firstfit(JCB *pr) /*首次适应作业分区*/
    {
     SUB *k;
     r=sub;   /*从空闲表头开始寻找*/
     while(r!=NULL)
      {
       if(((r->size)>(pr->size))&&(r->state=='n'))   /*有空闲分区大于作业大小的情况*/
          {
           pr->addr=r->addr;
           r->size-=pr->size;
           r->addr+=pr->size;
           flag=1;       /*分配成功标志位置1*/
           q=pr;
           q->state='r';
           lastsort();     /*插入已分配作业队列*/
           printf("作业%s的分区为[%s],首地址为%d.
    ",p->name,r->name,pr->addr);
           break;
          }
       else if(((r->size)==(pr->size))&&(r->state=='n'))    /*有空闲分区等于作业大小的情况*/
          {
           pr->addr=r->addr;
           flag=1;    /*分配成功标志位置1*/
           q=pr;
           lastsort();        /*插入已分配作业队列*/
           s=sub;       /*空闲分区已完成分配,应删除*/
           while(s->link!=r)  s=s->link;
           s->link=s->link->link;     /*删除空闲分区*/
           printf("作业%s的分区为[%s],首地址为%d.
    ",p->name,r->name,pr->addr);
           break;
         }
       else
             {r=r->link;  flag=0;}
    }
     if(flag==0)           /*作业过大的情况*/
     {
      printf("作业%s长度过大,内存不足,分区分配出错!
    ",p->name);
      is=1;
     }
    }
    
    void cyclefit(JCB *pr) /*循环首次适应作业分区*/
    {
     SUB *k;
     r=cur;   /*从当前指针开始寻找*/
     while(r!=NULL)
      {
       if(((r->size)>(pr->size))&&(r->state=='n'))   /*有空闲分区大于作业大小的情况*/
          {
           pr->addr=r->addr;
           r->size-=pr->size;
           r->addr+=pr->size;
           flag=1;       /*分配成功标志位置1*/
           cur=r;        /*更新当前指针*/
           q=pr;
           q->state='r';
           lastsort();             /*插入已分配作业队列*/
           printf("作业%s的分区为[%s],首地址为%d.
    ",p->name,r->name,pr->addr);
           break;
          }
       else if(((r->size)==(pr->size))&&(r->state=='n'))    /*有空闲分区等于作业大小的情况*/
          {
           pr->addr=r->addr;
           flag=1;    /*分配成功标志位置1*/
           cur=r;
           q=pr;
           lastsort();        /*插入已分配作业队列*/
           s=sub;      /*空闲分区已完成分配,应删除*/
           while(s->link!=r)  s=s->link;
           s->link=s->link->link;     /*删除空闲分区*/
           printf("作业%s的分区为[%s],首地址为%d.
    ",p->name,r->name,pr->addr);
           break;
         }
       else
         {
           r=r->link;
           if(r==NULL)      /*当前指针为空时,重新由空闲区队列之首寻找*/
              {
               k=cur;  /*作保存当前指针用*/
               cur=sub;  
               r=cur;
              }
           if(k==r)   /*又回到开始的指针时,确定为没有空间满足要求*/
             {
              cur=k;  
              break;
             }
           flag=0;  /*分配不成功标志*/
          }
      }
     if(flag==0)           /*作业过大的情况*/
     {
      printf("作业%s长度过大,内存不足,分区分配出错!
    ",p->name);
      is=1;
     }
    }
    
    void less_to_more()  /*把分区按大小从小到大排序*/
    {
     r=sub;
     sub=NULL;
     while(r!=NULL)
      {
       s=r;
       r=s->link;
       s->link=NULL;
       sort_sub(); /*调用排序函数*/
      }
    }
    
    void reclperfit(JCB *pr)       /*最佳适应回收区域,按分区大小排列*/
    { 
     SUB *k;
     r=sub;
     while(r!=NULL)
     {
      if(r->addr==((pr->addr)+(pr->size)))     /*回收区域有下邻*/
        {
          pr->size+=r->size;
          s=sub;
          isdown=1;     /*下邻标志位置1*/
          while(s!=NULL)
          {
           if(((s->addr)+(s->size))==(pr->addr))   /*有下邻又有上邻*/
            {
             s->size+=pr->size;
             k=sub;
             while(k->link!=r)  k=k->link;
             k->link=k->link->link;
             isup=1;      /*上邻标志位置1*/    
             break;
            }
           else 
            {s=s->link; isup=0;}    /*上邻标志位置0*/  
          }
           if(isup==0)               /*有下邻无上邻*/
           { 
             r->addr=pr->addr;
             r->size=pr->size;
           }
         break;       
        }
     else 
       {r=r->link; isdown=0;}     /*下邻标志位置0*/  
     }  
     if(isdown==0)              /*区域无下邻*/
        { 
          s=sub; 
          while(s!=NULL) 
          {
           if(((s->addr)+(s->size))==(pr->addr))   /*无下邻但有上邻*/
             { 
              s->size+=pr->size; 
              isup=1;        /*上邻标志位置1*/
              break;
             }
           else 
             { s=s->link; isup=0;}     /*上邻标志位置0*/
          } 
          if(isup==0)           /*无下邻且无上邻*/
               { 
                 k=getsub(SUB);   /*重新生成一个新的分区结点*/
                 strcpy(k->name,pr->name);
                 k->addr=pr->addr;
                 k->size=pr->size;
                 k->state='n';
                 r=sub;
                 while(r!=NULL)
                 {
                  if((r->size)>(k->size))   /*按分区大小排列,回收区域插在合适的位置*/
                    {
                      if(r==sub)       /*第一个空闲分区大于回收区域的情况*/
                          { k->link=r; sub->link=k; }
                      else
                         {
                          s=sub;
                          while(s->link!=r)  s=s->link;    
                          k->link=r;
                          s->link=k;                          
                         }
                      break;
                    }     
                  else r=r->link;
                 }
                if(r==NULL)     /*所有空闲分区都大于回收区域的情况*/ 
                   {
                     s=sub;
                     while(s->link!=NULL)  s=s->link;
                     s->link=k;
                     k->link=NULL;
                   }
               }    
        }
     printf("
    区域%s己回收.",pr->name);
    }         
       
    void reclfirst(JCB *pr)       /*首次适应与循环首次适应区域回收*/
    {
     SUB *k;
     r=sub;
     while(r!=NULL)
     {
      if(r->addr==((pr->addr)+(pr->size)))     /*回收区域有下邻*/
        {
          pr->size+=r->size;
          s=sub;
          isdown=1;     /*下邻标志位置1*/
          while(s!=NULL)
          {
           if(((s->addr)+(s->size))==(pr->addr))   /*有下邻又有上邻*/
            {
             s->size+=pr->size;
             k=sub;
             while(k->link!=r)  k=k->link;
             k->link=k->link->link;
             isup=1;      /*上邻标志位置1*/
             break;
            }
           else
            {s=s->link; isup=0;}    /*上邻标志位置0*/  
          }
           if(isup==0)               /*有下邻无上邻*/
           { 
             r->addr=pr->addr;
             r->size=pr->size;
           }
         break;       
        }
     else 
       {r=r->link; isdown=0;}     /*下邻标志位置0*/
     }  
     if(isdown==0)              /*区域无下邻*/
        { 
          s=sub;
          while(s!=NULL) 
          {
           if(((s->addr)+(s->size))==(pr->addr))   /*无下邻但有上邻*/
             {
              s->size+=pr->size; 
              isup=1;        /*上邻标志位置1*/
              break;
             }
           else 
             { s=s->link; isup=0;}     /*上邻标志位置0*/
          }
          if(isup==0)           /*无下邻且无上邻*/
               { 
                 k=getsub(SUB);   /*重新生成一个新的分区结点*/
                 strcpy(k->name,pr->name);
                 k->addr=pr->addr;
                 k->size=pr->size;
                 k->state='n';
                 r=sub;
                 while(r!=NULL)
                 {
                  if((r->addr)>(k->addr))   /*按分区首地址排列,回收区域插在合适的位置*/
                    {
                      if(r==sub)       /*第一个空闲分区首址大于回收区域的情况*/
                          { k->link=r; sub->link=k; }
                      else
                         {
                          s=sub;
                          while(s->link!=r)  s=s->link;    
                          k->link=r;
                          s->link=k;
                         }
                      break;
                    }
                  else r=r->link;
                 }
                if(r==NULL)     /*所有空闲分区的首址都大于回收区域首址的情况*/
                   {
                     s=sub;
                     while(s->link!=NULL)  s=s->link;
                     s->link=k;
                     k->link=NULL;
                   }
               }    
        }
     printf("
    区域%s己回收.",pr->name);
    }
    
    void print()  //初始化界面
    {printf("
    
    
    
    ");
     printf("		**************************************
    ");
     printf("			主存空间的分配与回收演示
    ");
     printf("		**************************************
    
    
    ");
     printf("				张文雅
    ");
     printf("				华南师范大学增城学院
    ");
     printf("				网络工程
    ");
     printf("				201306114136
    ");
     printf("				2015年6月
    ");
     printf("
    
    
    ");
     printf("			按任意键进入演示");
     getch();
     system("cls");
    }
    
    void init()
    {
     printf("
    
    
    
    			 1. 显示空闲分区                  
    ");
     printf("			 2. 分配作业                    
    ");
     printf("			 3. 回收作业                 
    ");
     printf("			 0. 返回菜单                     
    ");
     printf("			请选择你要的操作:");
     }
    
    firstfitf()             //首次适应算法
    {
     init();
     switch(getchar())
     {
      case '1':
              system("cls");
               disp();
               getch();
           system("cls");
           firstfitf();
           break;
      case '2':
                system("cls");
                       system("cls");
                       input();
                       printf("
    ");
                      while(num!=0)
                      {
                        p=ready;
                        ready=p->link;
                        p->link=NULL;
                        firstfit(p);
                        num--;
                       }
                      getch();
                       printf("
    		              完成分配后的空闲分区表             
    ");
                       disp();
                      printf("
    		                  已分配作业表                   
    ");
                      disp2();
                      if(is==0)
                       printf("
     全部作业已经被分配内存.");
                      else printf("
     作业没有全部被分配内存.
    ");
                      getch();
                      system("cls");
                      firstfitf();
                      break;
          case '3':
                      system("cls");
                       disp2();
                       printf("
    
    按任意键进行区域回收.");
                      printf("
    ");
                        while(as!=NULL)
                      {getch();
                       input2();
                       printf("按任意键继续...");
                        getch();
                        printf("
    ");
                        reclfirst(q);
                        getch();
                        printf("
    		              回收后的空闲分区表             
    ");
                        disp();
                        printf("
    		                已分配作业表                 
    ");
                        disp2();
                          printf("
    继续回收...(Enter)");
                       }
                        printf("
    所有已分配作业已完成!");
                        printf("
    Press any key to return...");
                        getch();
                      system("cls");
                      firstfitf();
                      break;
             case '0':
                     break;
             default:
                    getch();
                      system("cls");
                      firstfitf();
                      break;
         }
     }
    
    cyclefirstf()      //循环首次适应算法
    {
      init();
     switch(getchar())
     {
      case '1':
              system("cls");
               disp();
               getch();
           system("cls");
           cyclefirstf();
           break;
       case '2':
               system("cls");
                cur=sub;
                input();
                printf("
    ");
                while(num!=0)
                  {
                    p=ready;
                    ready=p->link;
                    p->link=NULL;
                    cyclefit(p);
                    num--;
                  }
                getch();
                printf("
    		              完成分配后的空闲分区表             
    ");
                disp();
                printf("
    		                已分配作业表                 
    ");
                disp2();
                if(is==0)
                   printf("
     全部作业已经被分配内存.");
                else printf("
     作业没有全部被分配内存.
    "); 
                getch();
                      system("cls");
                      cyclefirstf();
                      break;
            case '3':
                system("cls");
                       disp2();
                printf("
    
    按任意键进行区域回收.");
                while(as!=NULL)
                  {getch();
                   printf("
    ");
                   input2();
                   printf("按任意键继续...");
                   getch();
                   printf("
    ");
                   reclfirst(q);
                   getch();
                   printf("
    		              回收后的空闲分区表             
    ");
                   disp();
                   printf("
    		                已分配作业表                 
    ");
                   disp2();
                   printf("
    继续回收...(Enter)");
                  }
                printf("
    所有已分配作业已完成!");
                getch();
                      system("cls");
                      cyclefirstf();
                      break;
           case '0':
                   break;
             default:
                    getch();
                      system("cls");
                     cyclefirstf();
                      break;
      }
     }
    
     perfitf()  //最佳适应算法
     {
       init();
     switch(getchar())
     {
      case '1':
              system("cls");
              less_to_more();
               disp();
               getch();
           system("cls");
           perfitf();
           break;
      case '2':
             system("cls");
                cur=sub;
                input();
                printf("
    ");
                while(num!=0)
                  {
                    p=ready;
                    ready=p->link;
                    p->link=NULL;
                    less_to_more();   /*重新排列分区,按从小到大排列*/
                    perfit(p);
                    num--;
                  }
                getch();
                printf("
    
    		     完成分配后分区表(分区按由小到达排列)    
    ");
                disp();
                printf("
    		                 已分配作业表                  
    ");
                disp2();
                if(is==0)
                   printf("
     全部作业已经被分配内存.");
                else printf("
     作业没有全部被分配内存.
    ");
                getch();
           system("cls");
           perfitf();
           break;
      case '3':
                system("cls");
                       disp2();
              printf("
    
    按任意键进行区域回收.");
                while(as!=NULL)
                  {getch();
                   printf("
    ");
                   input2();
                   printf("按任意键继续...");
                   getch();
                   printf("
    ");
                   reclperfit(q);
                   getch();
                   printf("
    		              回收后的空闲分区表             
    ");
                   disp();
                   printf("
    		                已分配作业表                 
    ");
                   disp2();
                   printf("
    继续回收...(Enter)");
                  }
                printf("
    所有已分配作业已完成!");
                 getch();
           system("cls");
           perfitf();
           break;
       case '0':
                   break;
             default:
                    getch();
                      system("cls");
                    perfitf();
                      break;
      }
     }
    
    void menu()      /*菜单函数*/
    {
     int i;
     printf("
    
    
    		**************************************
    ");
     printf("			主存空间的分配与回收演示
    ");
     printf("		**************************************
    ");;
     printf("			
    
    ");
     printf("			 1. 首次适应算法                    
    ");
     printf("			 2. 循环首次适应算法                 
    ");
     printf("			 3. 最佳适应算法                     
    ");
     printf("			 0. 退出                            
    ");
     printf("			请选择你要的操作:");
     switch(getchar())
     {
      case '1':
                system("cls");
                firstfitf();
                getch();
                system("cls");
                menu();
                break;
      case '2':
                system("cls");
                 cyclefirstf();
                getch();
                system("cls");
                menu();
                break;  
      case '3':
                system("cls");
                    perfitf();
                getch();
                system("cls");
                menu();
                break;
      case '0':
     break;   
      default:
                getch();    
                system("cls"); 
                menu();     
                break;          
     }
    }                     
    void main()     /*主函数*/
    {
     init_sub();
     print();
     menu();
    }

    5.运行结果:

    六、实验总结

    用c语言编写了一个主存空间的分配和回收程序,加深了我对动态分区分配方式及其算法的理解。期间遇到了很多的困难,通过看课本,参考了网上的资料,也请教了同学,最终编写出来了。

  • 相关阅读:
    动手动脑
    加减乘除
    测试
    Java学习的第五十六天
    Java学习的第五十五天
    js判断一个时间是否在某一个时间段内
    js计算两个时间相差多少分钟
    js分钟转化为小时并且以某个数字进行递增
    关于Js debounce(防抖)函数和throttle(节流)小结
    webpack配置scss
  • 原文地址:https://www.cnblogs.com/iTues/p/4535012.html
Copyright © 2011-2022 走看看