操作系統之實驗四主存空間的分配和回收


                                                                                    實驗四主存空間的分配和回收

                                                     專業:商業軟件工程     班級:商軟2班     姓名:甘佳萍     學號:201406114207

一.    目的和要求

1.1.           實驗目的

用高級語言完成一個主存空間的分配和回收程序,以加深對動態分區分配方式及其算法的理解。

1.2.           實驗要求

采用連續分配方式之動態分區分配存儲管理,使用首次適應算法、循環首次適應算法、最佳適應算法和最壞適應算法4種算法完成設計。

(1)**設計一個作業申請隊列以及作業完成后的釋放順序,實現主存的分配和回收。采用分區說明表進行。

(2)或在程序運行過程,由用戶指定申請與釋放。

(3)設計一個空閑區說明表,以保存某時刻主存空間占用情況。

把空閑區說明表的變化情況以及各作業的申請、釋放情況顯示。

 

二.    實驗內容

第一步:

完成程序數據結構的創建,初始化內存分配情況,創建空閑分區表和已分配分區表。

第二步:

完成為某作業分配內存空間。

  1. 用戶輸入作業名稱;
  2. 判斷作業名稱是否已經存在,如果存在則要求用戶重新輸入;
  3. 用戶輸入作業所占空間大小;
  4. 判斷是否能夠在剩余的空閑區域中找到一塊放置該作業,如果不行則要求用戶重新輸入;
  5. 顯示菜單,由用戶選擇使用哪一種分配算法:

1)        首次適應算法

2)        循環首次適應算法

3)        最佳適應算法

4)        最壞適應算法

      6.為該作業分配內存空間,分配處理流程圖如下(size的值設定為1K)

      7.屏幕顯示分配后的內存分區情況。

第三步:

完成內存空間回收;

  1. 由用戶輸入作業的ID,決定所要終止的作業;
  2. 判斷是否存在用戶所輸入的ID,如果存在則進行終止,否則提示作業不存在;
  3. 判斷即將終止的作業前后是否有空閑區域,如果沒有則作業所占的空間獨立成為一個空閑塊,在未分配區表中增加一項;

(思考:如何判斷前后是否有空閑塊?)

      4.即將終止作業所占空間前后有空閑塊的情況:(X代表即將被終止的作業,黑色代表內存中的空閑塊)

所以,判斷某個即將被終止的作業所占空間前面是否有空閑塊的方法是:作業空間的起始地址A.begin是否等於某個空閑塊的結束地址B.end,若相等,則前面有空閑塊,則需要合並;若不相等則再判斷后面是否有空閑塊。

回答:如何判斷?

      5.進行四種情況的判斷,然后分別做出相應的區塊回收操作。

回答:如何處理回收?

      6.顯示回收后的內存使用情況。

 

根據指定的實驗課題,完成設計、編碼和調試工作,完成實驗報告

 

三、        實驗方法、步驟及結果測試

 1.      源程序名:壓縮包文件(rarzip)中源程序名OS.c

可執行程序名:OS.exe

 2.      原理分析及流程圖

主要總體設計問題。

(包括存儲結構,主要算法,關鍵函數的實現等)

存儲結構:

typedef struct free_table//定義一個空閑區說明表結構  
{     
    int num; //分區序號    
    long begin; //起始地址    
    long size;   //分區大小    
    int status;   //分區狀態 
}ElemType;

typedef struct Node// 線性表的雙向鏈表存儲結構 
{    
    ElemType data;     
    struct Node *prior; //前趨指針   
    struct Node *next;  //后繼指針 
}Node,*LinkList;    

LinkList first; //頭結點 
LinkList end;  //尾結點  
int flag;//記錄要刪除的分區序號   

Status Initblock()//開創帶頭結點的內存空間鏈表 
{     
    first=(LinkList)malloc(sizeof(Node));   
    end=(LinkList)malloc(sizeof(Node));   
    first->prior=NULL;   
    first->next=end;   
    end->prior=first;
    end->next=NULL; 
     end->data.num=1;   
     end->data.begin=40;   
     end->data.size=600;   
     end->data.status=0;  
     return SIZE; 
}

主要算法:

關鍵函數:

Status allocation(int a)
Status Best_fit(int request) 
Status deal1(Node *p)
Status deal2(Node *p) 
Status First_fit(int request) 
Status Initblock()
Status recovery(int flag)
void show()
void sort()
Status Worst_fit(int request)

3.      主要程序段及其解釋:

實現主要功能的程序段,重要的是程序的注釋解釋。        

源程序:

#include<stdio.h>  
#include<conio.h>
#include<string.h>
#include<stdlib.h> 

#define SIZE 1
#define ERROR 0 //出錯   
typedef int Status; 

typedef struct free_table//定義一個空閑區說明表結構  
{     
    int num; //分區序號    
    long begin; //起始地址    
    long size;   //分區大小    
    int status;   //分區狀態 
}ElemType;

typedef struct Node// 線性表的雙向鏈表存儲結構 
{    
    ElemType data;     
    struct Node *prior; //前趨指針   
    struct Node *next;  //后繼指針 
}Node,*LinkList;    

LinkList first; //頭結點 
LinkList end;  //尾結點  
int flag;//記錄要刪除的分區序號   

Status Initblock()//開創帶頭結點的內存空間鏈表 
{     
    first=(LinkList)malloc(sizeof(Node));   
    end=(LinkList)malloc(sizeof(Node));   
    first->prior=NULL;   
    first->next=end;   
    end->prior=first;
    end->next=NULL; 
     end->data.num=1;   
     end->data.begin=40;   
     end->data.size=600;   
     end->data.status=0;  
     return SIZE; 
}

//菜單
void menu()
{
    printf("\n                 |*************內存分配和回收***********|\n");
    printf("                 |======================================|\n");
    printf("                 |              0.退出                  |\n");
    printf("                 |              1.首次適應算法          |\n");
    printf("                 |              2.最佳適應算法          |\n");
    printf("                 |              3.最壞適應算法          |\n");
    printf("                 |======================================|\n");
}

void sort()//分區序號重新排序 
{    
    Node *p=first->next,*q;   
    q=p->next;    
    for(;p!=NULL;p=p->next)   
    {     
        for(q=p->next;q;q=q->next)    
        {       
            if(p->data.num>=q->data.num)       
            {          
                q->data.num+=1;        
            }    
        }     
    } 
 } 

//顯示主存分配情況 
void show()  
{  
    int flag=0;//用來記錄分區序號    
    Node *p=first;     
    p->data.num=0;     
    p->data.begin=0;     
    p->data.size=40;     
    p->data.status=1;     
    sort();      
    printf("\n\t\t》主存空間分配情況《\n");      
    printf("**********************************************************\n\n");     
    printf("分區序號\t起始地址\t分區大小\t分區狀態\n\n");     
    while(p)     
    {        
        printf("%d\t\t%d\t\t%d",p->data.num,p->data.begin,p->data.size);         
        if(p->data.status==0) printf("\t\t空閑\n\n");         
        else printf("\t\t已分配\n\n"); 
          p=p->next;      
    }      
    printf("**********************************************************\n\n"); 
}

//首次適應算法  
Status First_fit(int request) 
{   
    //為申請作業開辟新空間且初始化    
    Node *p=first->next;    
    LinkList temp=(LinkList)malloc(sizeof(Node));    
    temp->data.size=request;   
    temp->data.status=1;   
    p->data.num=1;   
    while(p)   
    {     
        if((p->data.status==0)&&(p->data.size==request))     
        {
            //有大小恰好合適的空閑塊       
            p->data.status=1;       
            return SIZE;        
            break;  
             }     
        else if((p->data.status==0) && (p->data.size>request))     
        {
            //有空閑塊能滿足需求且有剩余        
            temp->prior=p->prior;        
            temp->next=p;         
            temp->data.begin=p->data.begin;        
            temp->data.num=p->data.num;        
            p->prior->next=temp;         
            p->prior=temp;         
            p->data.begin=temp->data.begin+temp->data.size;        
            p->data.size-=request;        
            p->data.num+=1;        
            return SIZE;        
            break;     
        }     
        p=p->next;  
    }
     return ERROR; 
}   

//最佳適應算法  
Status Best_fit(int request) 
{    
    int ch; //記錄最小剩余空間    
    Node *p=first;     
    Node *q=NULL; //記錄最佳插入位置     
    LinkList temp=(LinkList)malloc(sizeof(Node)); 
     temp->data.size=request;    
     temp->data.status=1;     
     p->data.num=1;     
     while(p) //初始化最小空間和最佳位置    
     {      
         if((p->data.status==0) && (p->data.size>=request) )      
         {          
             if(q==NULL)             
             {              
                 q=p;               
                 ch=p->data.size-request;             
         }          
             else if(q->data.size > p->data.size)          
             {           
                 q=p;            
                 ch=p->data.size-request;          
             }      
         } 
          p=p->next;   
     }    
     if(q==NULL) return ERROR;//沒有找到空閑塊   
     else if(q->data.size==request)   
     {         
         q->data.status=1;         
         return SIZE;     
     }  
     else   
     {       
         temp->prior=q->prior;      
         temp->next=q;       
         temp->data.begin=q->data.begin;      
         temp->data.num=q->data.num;      
         q->prior->next=temp;      
         q->prior=temp;        
         q->data.begin+=request;      
         q->data.size=ch;      
         q->data.num+=1; 
         return SIZE;   
     }   
     return SIZE; 
}   

//最差適應算法  
Status Worst_fit(int request) 
{      
    int ch; //記錄最大剩余空間     
    Node *p=first->next;      
    Node *q=NULL; //記錄最佳插入位置      
    LinkList temp=(LinkList)malloc(sizeof(Node));      
    temp->data.size=request;     
    temp->data.status=1;     
    p->data.num=1;      
    while(p) //初始化最大空間和最佳位置      
    {          
        if(p->data.status==0 && (p->data.size>=request) )          
        {             
            if(q==NULL)            
            {                  
                q=p; 
                ch=p->data.size-request;             
            }             
            else if(q->data.size < p->data.size)            
            {             
                q=p;              
                ch=p->data.size-request;            
            }          
        }          
        p=p->next;      
    }      
    if(q==NULL) return ERROR;//沒有找到空閑塊     
    else if(q->data.size==request)      
    {         
        q->data.size=1;        
        return SIZE;      
    }     
    else      
    {
        temp->prior=q->prior;       
        temp->next=q;        
        temp->data.begin=q->data.begin;       
        temp->data.num=q->data.num;       
        q->prior->next=temp;       
        q->prior=temp;         
        q->data.begin+=request;       
        q->data.size=ch;       
        q->data.num+=1;       
        return SIZE; 
        }      
    return SIZE; 
}   

//分配主存  
Status allocation(int a) 
{    
    int request;//申請內存大小    
    printf("請輸入申請分配的主存大小(單位:KB):");    
    scanf("%d",&request);   
    if(request<0 ||request==0)      
    {        
        printf("分配大小不合適,請重試!");       
        return ERROR;     
    }    
    switch(a)   
    {      
    case 1: //默認首次適應算法 
          if(First_fit(request)==SIZE) printf("\t****分配成功!****");             
          else printf("\t****內存不足,分配失敗!****");             
          return SIZE;    
          break;      
    case 2: //選擇最佳適應算法              
        if(Best_fit(request)==SIZE) printf("\t****分配成功!****");             
        else printf("\t****內存不足,分配失敗!****");             
        return SIZE;             
        break;  
    case 3: //選擇最差適應算法              
        if(Worst_fit(request)==SIZE) printf("\t****分配成功!****");             
        else printf("\t****內存不足,分配失敗!****");             
        return SIZE;    
        break;   
    } 
}

Status deal1(Node *p)//處理回收空間 
{     
    Node *q=first;     
    for(;q!=NULL;q=q->next)    
    {       
        if(q==p)      
        {      
            if(q->prior->data.status==0&&q->next->data.status!=0)     
            {
                q->prior->data.size+=q->data.size;         
                q->prior->next=q->next;         
                q->next->prior=q->prior;         
                q=q->prior;         
                q->data.status=0;          
                q->data.num=flag-1;       
            }        
            if(q->prior->data.status!=0&&q->next->data.status==0)       
            {         
                q->data.size+=q->next->data.size;     
                q->next=q->next->next;         
                q->next->next->prior=q;        
                q->data.status=0;         
                q->data.num=flag;      
            }        
            if(q->prior->data.status==0&&q->next->data.status==0)      
            {    
                q->prior->data.size+=q->data.size;         
                q->prior->next=q->next;         
                q->next->prior=q->prior; 
                q=q->prior;         
                q->data.status=0;          
                q->data.num=flag-1;      
            }         
            if(q->prior->data.status!=0&&q->next->data.status!=0)       
            {    
                q->data.status=0;      
            }      
        }    
    }     
    return SIZE; 
}   

Status deal2(Node *p)//處理回收空間 
{     
    Node *q=first;
    for(;q!=NULL;q=q->next)    
    {       
        if(q==p)      
        {      
            if(q->prior->data.status==0&&q->next->data.status!=0)     
            {    
                q->prior->data.size+=q->data.size;         
                q->prior->next=q->next; 
                 q->next->prior=q->prior;         
                 q=p->prior;         
                 q->data.status=0;          
                 q->data.num=flag-1;       
}        
            if(q->prior->data.status!=0&&q->next->data.status==0)       
            {         
                q->data.status=0;     
}        
            if(q->prior->data.status==0&&q->next->data.status==0)      
            {    
                q->prior->data.size+=q->data.size;         
                q->prior->next=q->next;         
                q->next->prior=q->prior;         
                q=q->prior;         
                q->data.status=0;          
                q->data.num=flag-1;      
            }
             if(q->prior->data.status!=0&&q->next->data.status!=0)       
             {    
                 q->data.status=0;      
             }      
        }    
    }     
    return SIZE; 
}   

//主存回收  
Status recovery(int flag) 
{     
    Node *p=first;    
    for(;p!=NULL;p=p->next)     
    {      
        if(p->data.num==flag)     
        {     
            if(p->prior==first)
                {      
                if(p->next!=end)//當前P指向的下一個不是最后一個時       
                {        
                    if(p->next->data.status==0)      //與后面的空閑塊相連         
                    {                  
                        p->data.size+=p->next->data.size;                 
                        p->next->next->prior=p;                 
                        p->next=p->next->next; 
                         p->data.status=0;                 
                         p->data.num=flag;         
                    }        
                    else p->data.status=0;       
                }      
                if(p->next==end)//當前P指向的下一個是最后一個時       
                {               
                    p->data.status=0;         
                }    
            }
            //結束if(p->prior==block_first)的情況    
            else if(p->prior!=first)    
            {      
                if(p->next!=end)      
                {        
                    deal1(p);       
                }      
                else
                    {       
                    deal2(p);      
            }    
            }//結束if(p->prior!=block_first)的情況   
        }//結束if(p->data.num==flag)的情況   
}    
    printf("\t****回收成功****");    
    return SIZE;    
}  

void main() 
{      
    int i;  //操作選擇標記     
    int a;//算法選擇標記      
       
     while(1)
    {
     menu();
      printf("請選擇輸入所使用的內存分配算法 (0~3):");  
            scanf("%d",&a);   
     while(a<0||a>3)     
     {        
         printf("\n輸入錯誤,請重新選擇輸入所使用的內存分配算法 (0~3):");       
         scanf("%d",&a);      
     }
          switch(a)  
          {    
          case 1:printf("\n\t****使用首次適應算法:****\n");
              break;       
          case 2:printf("\n\t****使用最佳適應算法:****\n");
              break;       
          case 3:printf("\n\t****使用最壞適應算法:****\n");
              break;  
               case 0:printf("\n\t****退出內存分配與回收****\n");
              return;  
          } 
          Initblock(); //開創空間表     
          while(1)      
          {           
              show();          
              printf("\t1: 分配內存\t2: 回收內存\t0: 退出當前內存分配算法\n");         
              printf("請輸入您的操作:");         
              scanf("%d",&i);         
              if(i==1)            
                  allocation(a); // 分配內存         
              else if(i==2)  // 內存回收         
              {              
                  printf("請輸入您要釋放的分區號:");             
                  scanf("%d",&flag);             
                  recovery(flag); 
                  }          
              else if(i==0)    
              {    
                  printf("\n退出當前內存分配算法,返回主菜單\n");    
                  break; //退出   
              }          
              else //輸入操作有誤         
              {              
                  printf("輸入有誤,請重新輸入!");            
                  continue;         
              }     
          } 
     }
}

4.      運行結果及分析

一般必須配運行結果截圖,結果是否符合預期及其分析。

   (截圖需根據實際,截取有代表性的測試例子)

運行結果:

 

四、        實驗總結

     總之,編寫主存空間的分配和回收的過程有(如解決實際問題)。從解決實際問題的角度,我們可以這樣來看:首先要了解這個問題的基本要求,即輸入、輸出、完成從輸入到輸出的要求是什么;其次,從問題的要害入手,從前到后的解決問題的每個方面,即從輸入開始入手,着重考慮如何從輸入導出輸出。在這個過程中,可確定所需的變量、數組、函數,然后確定處理的過程--算法。可得出最后的結論,進而完成程序的編寫。經過這次實驗,我對主存空間的分配和回收有了深一步的了解,同時也初步了解了內存空間的工作原理。總的來說這個實驗不是很難,還有這個實驗很有趣。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM