內存分配與回收


一、實驗目的

為了合理地分配和使用這些存儲空間,當用戶提出申請主存儲器空間時,存儲管理必須根據申請者的要求,按一定的策略分析主存空間和使用情況,找出足夠的空閑區域給申請者。當作業撤離歸還主存資源時,則存儲管理要收回占用的主存空間。主存的分配和回收的實現是與主存儲器的管理方式有關的,通過本實驗幫助我們理解在不同的存儲管理方式下應怎樣實現主存空間的分配和回收。

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

二、實驗內容和要求

要求:

1)實現特定的內存分配算法

2)實現內存回收模擬

3)每種內存分配策略對應的碎片數統計

a.固定分區存儲管理;

b.動態分區分配存儲管理 

內容:

1) 固定分區存儲管理

假設內存容量為120KB,並且分別划分成8,16,32,64KB大小的塊各一塊。一個進程所需要的內存為0到100個KB。同時假設一個進程在運行過程中所需內存的大小不變。

模擬五個進程到達請求分配與運行完回收情況,輸出主存分配表.

2)動態分區分配存儲管理

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

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

(2)設計一個已占用分區表,以保存某時刻主存空間占用情況。

(3)設計一個空閑分區表,以保存某時刻主存空間剩余情況。

(4)用兩個表的變化情況,反應各進程所需內存的申請與釋放情況。

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

1. 源程序名:gu(rar或zip)中源程序名1.c,2.c

  1. 可執行程序名:1.exe,2.exe

原理分析及流程圖 

1.固定分區內存管理

主要設計思路:

1.固定分區內存管理

該程序定義一個數組home,由於固定分配好5個固定大小的內存空間,先將5個固定大小的內存空間的各個屬性先初始化,然提醒用戶,輸入要執行進程的名字和大小,當內存的大小大於且最接近進程的大小,還有沒有被占用,則將內存的state改為進程的名字,當下次用戶再輸入進程時,就不會去占用已經被其他進程占用的內存塊。

2.動態分區分配存儲管理 

該程序定義兩個數組分別存放空閑區和作業區的起始地址,長度,結束地址。先將空閑區的個數初始化為1,然后提醒用戶輸入進程的大小,相應的在作業新增一條數據,在空閑區則少一條數據。

主要程序段及其解釋:

1.固定分區內存管理

typedef struct save{

    int sort;

    int size;

    int start;

    char state;

}node;

node home[10];

//初始化內存塊的各個屬性

void inflate()

{

    home[1].sort=1;

    home[1].size=8;

    home[1].start=30;

    home[1].state='0';

 

    home[2].sort=2;

    home[2].size=16;

    home[2].start=38;

    home[2].state='0';

 

    home[3].sort=3;

    home[3].size=32;

    home[3].start=54;

    home[3].state='0';

 

    home[4].sort=4;

    home[4].size=64;

    home[4].start=118;

    home[4].state='0';

}

//顯示各個內存塊的信息

void show()

{

    int i;

    printf("show the message\n");

    for(i=1;i<5;i++){

     printf("%5d%5d%5d%5c",home[i].sort,home[i].size,home[i].start,home[i].state);

     printf("\n");

    }

}

main()

{

char name;

int m;

int j,flag=1;

inflate();//初始化內存塊

show();

//定義一個標志位flag,如果flag為1則一直提醒用戶輸入進程,否則,內存塊已經被全部占用了,無法為其他進程分配內存空間。

while(flag)

{

printf("please input the process of name and size\n");

scanf("%c%d",&name,&m);

flag=0;

for(j=1;j<5;j++){

    if(home[j].state=='0' && home[j].size>m){

       home[j].state=name;

        flag=1;

       break;

    }

}

if(flag==0){

printf("無法分配\n");

}

for(j=1;j<5;j++)

{

printf("%5d%5d%5d%5c",home[j].sort,home[j].size,home[j].start,home[j].state);

printf("\n");

if(home[j].state=='0')

{

    flag=1;

}

}

getchar();

}

  1. 動態分區分配存儲管理 

#define N 10000

int xian;//空閑分區的個數

int zuo;//作業區的個數

struct kongxian

{

int start;  //起址

int end;    //結束

int length;  //長度

}kongxian[N];

struct zuoye

{

int start;  //起址

int end;   //結束

int length;  //長度

}zuoye[N];

int cmp1(const void *a,const void *b)

{

return (*(struct kongxian *)a).start-(*(struct kongxian *)b).start;

}

int cmp2(const void *a,const void *b)

{

return (*(struct zuoye *)a).start-(*(struct zuoye *)b).start;

}

void init()

{

xian=1;  //初始時只有一個空閑區

zuo=0;  //初始沒有作業

kongxian[0].start=0;

kongxian[0].end=1023;

kongxian[0].length=1024;

}

void print1() //打印空閑分區

{

int i;

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

printf("空閑分區ID:%d 起止:%d 結束:%d 長度:%d\n",i,kongxian[i].start,kongxian[i].end,kongxian[i].length);

}

void print2() //打印作業分區

{

int i;

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

printf("作業分區ID:%d 起止:%d 結束:%d 長度:%d\n",i,zuoye[i].start,zuoye[i].end,zuoye[i].length);

}

int main()

{

int i,j,k,t,len,flag,id;

int front,middle, behind;

int t1,t2;

init();

print1();

printf("輸入1裝入新作業,輸入0回收作業,輸入-1結束\n");

while(scanf("%d",&t)!=EOF)

{

    if(t==1)  //裝入新作業

    {

        printf("請輸入作業的占用空間的長度 ");

        scanf("%d",&len);

        flag=0;

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

        {

           if(kongxian[i].length>=len)  //首次適應算法

           {

               flag=1;

               break;

           }

        }

        if(!flag)

        {

           printf("內存分配失敗\n");

        }

        else

        {

           //將該作業加入作業區里

           zuoye[zuo].start=kongxian[i].start;

           zuoye[zuo].end=zuoye[zuo].start+len;

           zuoye[zuo].length=len;

           zuo++;  //作業數加1

           if(kongxian[i].length==len) //該分區全部用於分配,刪除該空閑分區

           {

               for(j=i;j<xian-1;j++)

               {

                  kongxian[j].start=kongxian[j+1].start;

                  kongxian[j].end=kongxian[j+1].end;

                  kongxian[j].length=kongxian[j+1].length;

               }

               xian--;

           }

           else  //該空閑分區部分用於分配,剩余的留在空閑分區中

           {

               kongxian[i].start+=len;

               kongxian[i].length-=len;

           }

        }

    }

    else if(t==0)

    {

        printf("輸入要回收的作業ID ");

            scanf("%d",&id);

        front=middle=behind=0;

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

        {

           if(kongxian[i].start>zuoye[id].end)

           break;

           if(kongxian[i].end==zuoye[id].start)  //待回收的作業上面有空閑分區

           {

               front=1;

               t1=i;

           }

           if(kongxian[i].start==zuoye[id].end)  //待回收的作業下面有空閑分區

           {

               behind=1;

               t2=i;

           }

        }

        if(!front&&!behind)  //待回收的作業上下均沒有空閑分區

        {

           kongxian[xian].start=zuoye[id].start;

           kongxian[xian].end=zuoye[id].end;

           kongxian[xian].length=zuoye[id].length;

           xian++;  //空閑分區增加一個

           qsort(kongxian,xian,sizeof(struct kongxian),cmp1); //插入空閑分區后排序

           for(j=id;j<zuo-1;j++)  //在作業分區中刪除該作業

           {

               zuoye[j].start=zuoye[j+1].start;

               zuoye[j].end=zuoye[j+1].end;

               zuoye[j].length=zuoye[j+1].length;

            }

           zuo--;

        }

        if(front &&behind)  //待回收的作業上下均有空閑分區

        middle=1;

        if(front&&!middle)  //合並待回收的作業和上面的空閑分區

        {

           kongxian[t1].end+=zuoye[id].length;

           kongxian[t1].length+=zuoye[id].length;

           for(j=id;j<zuo-1;j++)  //在作業分區中刪除該作業

           {

               zuoye[j].start=zuoye[j+1].start;

               zuoye[j].end=zuoye[j+1].end;

               zuoye[j].length=zuoye[j+1].length;

            }

           zuo--;

        }

        if(middle)  //合並待回收的作業和上下的空閑分區

        {

           kongxian[t1].end=kongxian[t2].end;

           kongxian[t1].length+=(zuoye[id].length+kongxian[t2].length);

           //刪除空閑分區t2

           for(j=t2;j<xian-1;j++)

           {

               kongxian[j].start=kongxian[j+1].start;

               kongxian[j].end=kongxian[j+1].end;

               kongxian[j].length=kongxian[j+1].length;

           }

           xian--;

           for(j=id;j<zuo-1;j++)  //在作業分區中刪除該作業

           {

               zuoye[j].start=zuoye[j+1].start;

               zuoye[j].end=zuoye[j+1].end;

               zuoye[j].length=zuoye[j+1].length;

            }

           zuo--;

        }

        if(behind &&!middle) //合並待回收的作業和下面的分區

        {

           kongxian[t2].start-=zuoye[id].length;

           kongxian[t2].length+=zuoye[id].length;

           for(j=id;j<zuo-1;j++)  //在作業分區中刪除該作業

           {

               zuoye[j].start=zuoye[j+1].start;

               zuoye[j].end=zuoye[j+1].end;

               zuoye[j].length=zuoye[j+1].length;

            }

           zuo--;

        }

        }

    else

    {

         printf("操作結束\n");

         break;

    }

    print1();

    print2();

}

return 0;

}

  1. 2.     運行結果及分析

1.固定分區內存管理

2. 動態分區分配存儲管理 

四、實驗總結

通過這次實驗,與同學交流思考,以及自己在課后的思考和上網查閱相關程序片段,摘網上的程序,並理解了網上程序的算法實現過程。本次實驗感觸最深的是自己C語言基礎薄,當然也有很大的收獲就是鍛煉了自己調試程序的能力以及編程思維得到鍛煉。還有一個重要的體會是要善於運用網絡上的一些有用的資源,它可以成為你學習的一種很有用的工具。


免責聲明!

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



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