實驗四主存空間的分配和回收
14商業軟件工程專業 姓名:陳彥生 學號:201406114124
一、目的和要求
1. 實驗目的
用高級語言完成一個主存空間的分配和回收程序,以加深對動態分區分配方式及其算法的理解。
2.實驗要求
采用連續分配方式之動態分區分配存儲管理,使用首次適應算法、循環首次適應算法、最佳適應算法和最壞適應算法4種算法完成設計(任選兩種算法)。
(1)設計一個作業申請隊列以及作業完成后的釋放順序,實現主存的分配和回收。采用分區說明表進行。
(2)或在程序運行過程,由用戶指定申請與釋放。
(3)設計一個空閑區說明表,以保存某時刻主存空間占用情況。把空閑區說明表的變化情況以及各作業的申請、釋放情況顯示。
二、實驗內容
編寫並調試一個模擬的內存分配與回收程序,使用首次適應算法、循環首次適應算法對內存空間的分配與回收。
三、實驗方法、步驟及結果測試
1. 源程序名:a.cpp
可執行程序名:a.exe
2. 原理分析
(1)編寫該程序首先要給定一個一定空間大小的內存,即申請空閑區空間最大值,並且要定義空間的各分區的作業標號、分區起始地址、分區長度,單位為字節、分區表的狀態位、前向指針、后向指針、已分配分區表、空閑分區等。
(2)通過定義空間分區后,還要定義空間分區鏈表並對其進行初始化,對空閑分區和已分配分區進行鏈表訪問,對於空閑分區可以分配給新進來的進程使用,對於已分配的分區,則等進程執行結束后在回收空間,恢復空閑區。通過鏈表的訪問實現整個空間分區的分配與回收。
3. 主要程序段及其解釋:
#include<stdio.h> #include<stdlib.h> #include <conio.h> #define nil -1 #define NULL 0 #define maxisize 600 //用戶的空閑區空間最大值 #define minisize 4 #define getspace(type) (type*)malloc(sizeof(type)) //分配空間 struct table{ char job; //作業標號 float address; //分區起始地址 float length; //分區長度,單位為字節 int flag; //分區表的標志 struct table *FRlink; //前向指針 struct table *RElink; //后向指針 }*free_table=NULL,*place; //已分配分區表,空閑分區表 typedef struct table FRtable; //空間分區鏈表初始化 FRtable *init(FRtable *tb) { tb->FRlink=NULL; tb->job=nil; tb->address=1064; tb->length=1664; tb->flag=0; tb->RElink=NULL; return tb; } //主存分配函數,為作業job分配大小為xk的分區空間 void allocate(char job,float xk,int choice) { FRtable *tb,*link; int k=0; float temp=600; if (free_table->FRlink==NULL&&free_table->RElink==NULL) {//給首個作業分配空間,改寫分區鏈表 free_table->job=job; free_table->length=xk; free_table->flag=1; if (xk<maxisize) { tb=getspace(FRtable); free_table->RElink=tb; tb->FRlink=free_table; tb->job=nil; tb->address=1064+xk; tb->length=maxisize-xk; tb->flag=0; } if (choice==2) {//鏈接成循環鏈表 free_table->FRlink=tb; tb->RElink=free_table; place=tb; } else { free_table->FRlink=NULL; if (xk<maxisize) tb->RElink=NULL; } k=1; } else { if (2==choice) tb=place;//采用CFF時將ta定位到上次找到的合適空間分區的下個空間分區 else tb=free_table; while(tb!=NULL) { if (3==choice) { while(tb!=NULL) { if (tb->length>=xk&&tb->flag==0) if (tb->length<temp) {place=tb;temp=tb->length;} //選擇最適合空間 tb=tb->RElink; } tb=place; } if (tb->length>=xk&&tb->flag==0) if (tb->length-xk<=minisize) {//當搜索到的空間大小<=xk+minisize時,將空間全部分配給作業 tb->job=job; tb->flag=1; place=tb->RElink; k=1; break; } else {//當搜索到的空間大小>xk+minisize時,將空間划分,再分配給作業 link=getspace(FRtable); link->length=tb->length-xk; tb->job=job; tb->length=xk; tb->flag=1; link->RElink=tb->RElink; if (NULL!=tb->RElink) tb->RElink->FRlink=link; tb->RElink=link; link->FRlink=tb; link->job=nil; link->address=tb->address+xk; link->flag=0; place=link; k=1; break; } tb=tb->RElink; } } if (0==k) {//未尋找到合適的空間分區,返回 printf(">>空間申請失敗! \n"); return; } } //主存回收函數,回收作業job所占用的分區空間 void reclaim(char job,int choice) { int bool1=0,bool2=0; FRtable *tb,*link; tb=free_table; if (2==choice) link=tb; else link=NULL; do { if (job==tb->job&&1==tb->flag) break; tb=tb->RElink; if (tb==link) { printf("\n>>抱歉,不存在作業%c! \n",job); return; } }while(tb!=link); bool1=(NULL==tb->FRlink||tb->FRlink==tb->RElink)? 1:tb->FRlink->flag; bool2=(NULL==tb->RElink||tb->FRlink==tb->RElink)? 1:tb->RElink->flag; if (bool1&&bool2) { tb->job=nil; tb->flag=0; } else if ((NULL==tb->FRlink||1==tb->FRlink->flag)&&0==tb->RElink->flag) { link=tb->RElink; tb->job=nil; tb->length+=link->length; tb->flag=0; tb->RElink=link->RElink; if (NULL!=link->RElink) link->RElink->FRlink=tb; free(link); } else if (0==tb->FRlink->flag&&1==tb->RElink->flag) { link=tb->FRlink; link->length+=tb->length; link->RElink=tb->RElink; tb->RElink->FRlink=link; if (free_table==tb) free_table=link; free(tb); } else if (0==tb->FRlink->flag&&0==tb->RElink->flag) { link=tb->FRlink; link->length=link->length+tb->length+tb->RElink->length; link->RElink=tb->RElink->RElink; if (NULL!=tb->RElink->RElink) tb->RElink->RElink->FRlink=link; if (free_table==tb) free_table=link; free(tb); free(tb->RElink); } } //顯示空間分區鏈表 void display(FRtable *tb,int choice) { // clrscr(); FRtable *temp; if (2==choice) temp=tb; else temp=NULL; printf("\n\t標號\t起始地址\t分區大小(KB)\t 標志\n"); printf("\n\t sys\t 1024.00\t 40.00\t\t 1\n"); do { printf("\n\t %c\t %.2f\t %.2f\t\t %d\n",tb->job,tb->address,tb->length,tb->flag); tb=tb->RElink; }while(temp!=tb); } //主函數 int main() { int i,a,choice; float xk; char job; FRtable *ta=getspace(FRtable); free_table=init(ta); do{ printf("\n 分區分配算法:\n\t0 - 退出(Exit)\n\t1 - 首次適應算法(FF)\n\t2 - 循環首次適應算法(CFF)\n \n"); printf(">>請選擇相應的算法:"); scanf("%d",&choice); if (0==choice) exit(0); }while(0>choice&&2<choice); while(1) { printf("\n 菜單:\n\t0 - 退出(Exit)\n\t1 - 申請空間(Allocation)\n\t2 - 回收空間(Reclaim) \n"); printf(">>請選擇你的操作:"); scanf("%d",&a); switch(a) { //a=0,程序結束 case 0:exit(0); //a=1,分配主存空間 case 1:printf(">>請輸入作業標號和所需要申請的空間:"); scanf("%*c%c%f",&job,&xk); allocate(job,xk,choice); display(free_table,choice); break; //a=2,回收主存空間 case 2:printf(">>請輸入你想回收的作業的相應標號:"); scanf("%*c%c",&job); reclaim(job,choice); display(free_table,choice); break; default:printf(">>ERROR:No thie choose! \n"); } } }
4.運行結果
如上圖所示,當輸入需要申請的空間和標號后,空閑分區會分配相應的空間大小,當輸入回收的標號時,內存會回收相應大小的空間。根據實驗結果顯示,實驗已達到預期效果。
四、實驗總結
(1)本次實驗是有關內存空間分配的算法的實現,實驗內容相對之前的進程調度稍微簡潔些,但是基本實現的數據結構的鏈表算法是一樣的,還是需要通過申請空間,定義分區大小,然后通過鏈表對各空閑分區進行相應的內存分配。
(2)雖然對實驗步驟比較清晰,對首次適應算法、循環首次適應算法的知識理解得比較好,但是在對如何通過這些算法去實現這個內存分配的實驗,還是遇到很多困難,比如鏈表初始化與訪問的算法基礎掌握得不好,還有一些基本的C語言的語法結構掌握不熟練,而且對算法與與程序之間的思維不清晰,導致在寫程序中出現較多問題,然后通過查找課本,上網搜尋資料,詢問同學進行幫助解答,最后得到基本的實驗程序。