第一篇:操作系統(tǒng)實(shí)驗(yàn)報告-可變分區(qū)存儲管理方式的內(nèi)存分配回收
實(shí)驗(yàn)三 可變分區(qū)存儲管理方式的內(nèi)存分配回收
一.實(shí)驗(yàn)?zāi)康?/p>
(1)深入了解可變分區(qū)存儲管理方式的內(nèi)存分配回收的實(shí)現(xiàn)。
二.實(shí)驗(yàn)內(nèi)容
編寫程序完成可變分區(qū)存儲管理方式的內(nèi)存分配回收,要求有內(nèi)存空間分配表,并采用最優(yōu)適應(yīng)算法完成內(nèi)存的分配與回收。
三.實(shí)驗(yàn)原理
在可變分區(qū)模式下,在系統(tǒng)初啟且用戶作業(yè)尚未裝入主存儲器之前,整個用戶區(qū)是一個大空閑分區(qū),隨著作業(yè)的裝入和撤離,主存空間被分成許多分區(qū),有的分區(qū)被占用,而有的分區(qū)時空閑的。為了方便主存空間的分配和去配,用于管理的數(shù)據(jù)結(jié)構(gòu)可由兩張表組成:“已分配區(qū)表”和“未分配區(qū)表”。在“未分配表中”將空閑區(qū)按長度遞增順序排列,當(dāng)裝入新作業(yè)時,從未分配區(qū)表中挑選一個能滿足用戶進(jìn)程要求的最小分區(qū)進(jìn)行分配。這時從已分配表中找出一個空欄目登記新作業(yè)的起始地址和占用長度,同時修改未分配區(qū)表中空閑區(qū)的長度和起始地址。當(dāng)作業(yè)撤離時已分配區(qū)表中的相應(yīng)狀態(tài)變?yōu)椤翱铡?,而將收回的分區(qū)登記到未分配區(qū)表中,若有相鄰空閑區(qū)再將其連接后登記??勺兎謪^(qū)的回收算法較為復(fù)雜,當(dāng)一個作業(yè)撤離時,可分為4種情況:其臨近都有作業(yè)(A和B),其一邊有作業(yè)(A或B),其兩邊均為空閑區(qū)。尤其重要的是,在程序中利用“new類型T(初值列表)”申請分配用于存放T類型數(shù)據(jù)的內(nèi)存空間,利用“delete指針名”釋放指針?biāo)赶虻膬?nèi)存空間。
四.實(shí)驗(yàn)部分源程序
#include
int start,end;// 起始,結(jié)束
int length;// 長度大小
struct SNode *next;// 指向下一結(jié)點(diǎn)的指針 }* SP;SP Head=(SP)malloc(sizeof(SNode));// 全局變量,內(nèi)存空間頭結(jié) void DispSpace(){ // 顯示內(nèi)存空間分配情況
SP p=Head->next;
cout<<“n 空閑區(qū)說明表 n”
<<“---地址--長度---n”;
while(p)
{
cout<<“
”<
start
<<“
”<
length< p=p->next; } cout<<“----------------n”;} void Initial(){ // 初始化說明表 SP p,q; p=(SP)malloc(sizeof(SNode)); q=(SP)malloc(sizeof(SNode)); p->start=14;p->length=12;p->end=26; q->start=32;q->length=96;q->end=128;// 指導(dǎo)書上的作業(yè)分配 Head->next=p;// 與頭結(jié)點(diǎn)連接 p->next=q; q->next=NULL; DispSpace();} void Allocation(int len){ // 分配內(nèi)存給新作業(yè) SP p=Head->next,q; while(p){ if(p->length < len) p=p->next; else if(p->length > len) { p->start=p->start+len; p->length=p->length-len; cout<<“分配成功!n”; DispSpace();return; } else {//當(dāng)兩者長度相等 q=p->next; p->next=q->next; cout<<“分配成功!n”; DispSpace();return; } } cout<<“分配失敗!n”; DispSpace();return;} void CallBack(int sta,int len){ // 回收內(nèi)存 SP p=Head,q=p->next,r;// 開始地址和長度 p->end=0; int en=sta+len; while(q){ if(sta == 0){ // 初始地址為0 if(en == q->start){ // 正好回收 q->start=0; q->length=q->end; return; } else { r=(SP)malloc(sizeof(SNode)); r->start=sta;r->length=len;r->end=en; p->next=r; r->next=q; return; } } else if((p->end < sta)&&(q->start > en)){ // 上鄰區(qū) r=(SP)malloc(sizeof(SNode)); r->start=sta;r->length=len;r->end=en; p->next=r; r->next=q; return; } else if((p->end < sta)&&(q->start == en)){ // 鄰區(qū)相接 q->start=sta; q->length=q->end-sta; return; } else if((p->end == sta)&&(q->start < en)){ // 下鄰區(qū) p->end=en; p->length=en-p->start; return; } else if(p->end==sta && q->start==en){ // 鄰區(qū)相接 p->end=q->end; p->length=p->end-p->start; p->next=q->next; return; } else { p=p->next; q=q->next; } } } void main(){ Initial(); cout<<“現(xiàn)在分配大小為 6K 的作業(yè) 4 申請裝入主存: ”; Allocation(6);// 分配時參數(shù)只有長度 //--------指導(dǎo)書測試數(shù)據(jù)演示---------- cout<<“現(xiàn)回收作業(yè) 3(起址10,長度4)n”; CallBack(10,4); DispSpace(); cout<<“現(xiàn)回收作業(yè) 2(起址26,長度6)n”; CallBack(26,6); DispSpace(); //---------------演示結(jié)束------------- system(“pause”);} 五.實(shí)驗(yàn)結(jié)果與體會 我的體會: #include #include #include #include const int MJ=10;//假定系統(tǒng)允許的最大作業(yè)數(shù)量為10 typedef struct node{ int address; int length; char tag[10]; }job; job frees[MJ]; int free_quantity; job occupys[MJ]; int occupy_quantity; int read() { FILE *fp; char fn[10]; cout<<“請輸入初始空閑表文件名:”; cin>>fn; if((fp=fopen(fn,“r”))==NULL){ 其意義是在當(dāng)前目錄下打開文件file a,只允許進(jìn)行“讀”操作,并使fp指向該文件 cout<<“錯誤,文件打不開,請檢查文件名”< } else{ while(!feof(fp)){ fscanf(fp,“%d,%d”,&frees[free_quantity].address,&frees[free_quantity].length);free_quantity++;fscanf(文件指針,格式字符串,輸入表列); } return 1; } return 0; } void sort() { int i,j,p; for(i=0;i p=i; for(j=i+1;j if(frees[j].address p=j; } } if(p!=i){ frees[free_quantity]=frees[i]; frees[i]=frees[p]; frees[p]=frees[free_quantity]; } } } void view() { int i; cout< cout<<“輸出空閑區(qū)表:n起始地址 分區(qū)長度狀態(tài)n”< for(i=0;i cout.setf(2); cout.width(12); cout< cout.width(10); cout< cout.width(8); cout< } cout< cout<<“輸出已分分區(qū)表:n起始地址 分區(qū)長度 占用作業(yè)名n”< for(i=0;i cout.setf(2); cout.width(12); cout< cout.width(10); cout< cout.width(8); cout< } } void ear() { char job_name[10]; int job_length; int i,j,flag,t; cout<<“請輸入分配內(nèi)存的作業(yè)名和空間大小:”; cin>>job_name; cin>>job_length; flag=0; for(i=0;i if(frees[i].length>=job_length){ flag=1; } } if(flag==0){//未找到空閑區(qū),返回 cout< } else{ t=0; i=0; while(t==0){ if(frees[i].length>=job_length){//找到可用空閑區(qū),開始分配 t=1; } i++; } i--; occupys[occupy_quantity].address=frees[i].address;//修改已分配區(qū)表 strcpy(occupys[occupy_quantity].tag,job_name); occupys[occupy_quantity].length=job_length; occupy_quantity++; if(frees[i].length>job_length){ frees[i].address+=job_length; frees[i].length-=job_length; } else{ for(j=i;j frees[j]=frees[j+1]; } free_quantity--; cout<<“內(nèi)存空間成功:)”< } } } void reclaim()//回收作業(yè)所占的內(nèi)存空間 { char job_name[20]; int i,j,flag,p=0; int address; int length;//尋找已分分區(qū)表中對應(yīng)的登記項(xiàng) cout<<“輸入要回收分區(qū)的作業(yè)名:”; cin>>job_name; flag=-1; for(i=0;i if(!strcmp(occupys[i].tag,job_name)){ flag=i; address=occupys[i].address; length=occupys[i].length; } } if(flag==-1){ //在已分分區(qū)表中找不到作業(yè) cout<<“沒有這個作業(yè)名”< } else{//修改空閑區(qū)表,加入空閑表 for(i=0;i if((frees[i].address+frees[i].length)==address){ if(((i+1) for(j=i+1;j frees[j]=frees[j+1]; } free_quantity--; p=1; } else{ frees[i].length+=length; p=1; } } if(frees[i].address==(address+length)){ frees[i].address=address; frees[i].length+=length; p=1; } } if(p==0){ frees[free_quantity].address=address; frees[free_quantity].length=length; free_quantity++; }//刪除分配表中的該作業(yè) for(i=flag;i occupys[i]=occupys[i+1]; } occupy_quantity--; } } void main() { int flag=0; int t=1; int chioce=0; int i; for(i=0;i frees[i].address=-1;//空閑區(qū)表初始化 frees[i].length=0; strcpy(frees[i].tag,“free”); occupys[i].address=-1;//已分分區(qū)表初始化 occupys[i].length=0; strcpy(occupys[i].tag,“"); } free_quantity=0; occupy_quantity=0; flag=read(); while(flag==1){ sort(); cout<<”選擇功能項(xiàng):(0-退出,1-分配內(nèi)存,2-回收內(nèi)存,3-顯示內(nèi)存)n“< cin>>chioce; switch(chioce){ case 0: flag=0; break; case 1: ear(); break; case 2: reclaim(); break; case 3: view(); break; default: cout<<”沒有該選項(xiàng)n"< } } } 一.實(shí)驗(yàn)?zāi)康?/p> 通過編寫和調(diào)試存儲管理的模擬程序以加深對存儲管理方案的理解,熟悉可變分區(qū)存儲管理的內(nèi)存分配和回收。二.實(shí)驗(yàn)內(nèi)容 1.確定內(nèi)存空間分配表; 2.采用最優(yōu)適應(yīng)算法完成內(nèi)存空間的分配和回收; 3.編寫主函數(shù)對所做工作進(jìn)行測試。 三.實(shí)驗(yàn)背景材料 實(shí)現(xiàn)可變分區(qū)的分配和回收,主要考慮的問題有三個:第一,設(shè)計記錄內(nèi)存使用情況的數(shù)據(jù)表格,用來記錄空閑區(qū)和作業(yè)占用的區(qū)域;第二,在設(shè)計的數(shù)據(jù)表格基礎(chǔ)上設(shè)計內(nèi)存分配算法;第三,在設(shè)計的數(shù)據(jù)表格基礎(chǔ)上設(shè)計內(nèi)存回收算法。 首先,考慮第一個問題,設(shè)計記錄內(nèi)存使用情況的數(shù)據(jù)表格,用來記錄空間區(qū)和作業(yè)占用的區(qū)域。 由于可變分區(qū)的大小是由作業(yè)需求量決定的,故分區(qū)的長度是預(yù)先不固定的,且分區(qū)的個數(shù)也隨內(nèi)存分配和回收變動??傊?,所有分區(qū)情況隨時可能發(fā)生變化,數(shù)據(jù)表格的設(shè)計必須和這個特點(diǎn)相適應(yīng)。由于分區(qū)長度不同,因此設(shè)計的表格應(yīng)該包括分區(qū)在內(nèi)存中的起始地址和長度。由于分配時空閑區(qū)有時會變成兩個分區(qū):空閑區(qū)和已分分區(qū),回收內(nèi)存分區(qū)時,可能會合并空閑分區(qū),這樣如果整個內(nèi)存采用一張表格記錄己分分區(qū)和空閑區(qū),就會使表格操作繁瑣。分配內(nèi)存時查找空閑區(qū)進(jìn)行分配,然后填寫己分配區(qū)表,主要操作在空閑區(qū);某個作業(yè)執(zhí)行完后,將該分區(qū)變成空閑區(qū),并將其與相鄰的空閑區(qū)合并,主要操作也在空閑區(qū)。由此可見,內(nèi)存的分配和回收主要是對空閑區(qū)的操作。這樣為了便于對內(nèi)存空間的分配和回收,就建立兩張分區(qū)表記錄內(nèi)存使用情況,一張表格記錄作業(yè)占用分區(qū)的“己分分區(qū)表”;一張是記錄空閑區(qū)的“空閑區(qū)表”。這兩張表的實(shí)現(xiàn)方法一般有兩種:一種是鏈表形式,一種是順序表形式。在實(shí)驗(yàn)中,采用順序表形式,用數(shù)組模擬。由于順序表的長度必須提前固定,所以無論是“已分分區(qū)表”還是“空閑區(qū)表”都必須事先確定長度。它們的長度必須是系統(tǒng)可能的最大項(xiàng)數(shù)。 “已分分區(qū)表”的結(jié)構(gòu)定義 #define n 10 //假定系統(tǒng)允許的最大作業(yè)數(shù)量為n struct { float address;//已分分區(qū)起始地址 float length;//已分分區(qū)長度、單位為字節(jié) int flag;//已分分區(qū)表登記欄標(biāo)志,“0”表示空欄目,實(shí)驗(yàn)中只支持一個字符的作業(yè)名 }used_table[n];//已分分區(qū)表 “空閑區(qū)表”的結(jié)構(gòu)定義 #define m 10 //假定系統(tǒng)允許的空閑區(qū)最大為m struct { float address;//空閑區(qū)起始地址 float length;//空閑區(qū)長度、單位為字節(jié) int flag;//空閑區(qū)表登記欄標(biāo)志,“0”表示空欄目,“1”表示未分配 }used_table[n];//空閑區(qū)表 第二,在設(shè)計的數(shù)據(jù)表格基礎(chǔ)上設(shè)計內(nèi)存分配。 裝入一個作業(yè)時,從空閑區(qū)表中查找滿足作業(yè)長度的未分配區(qū),如大于作業(yè),空閑區(qū)劃 第1頁 分成兩個分區(qū),一個給作業(yè),一個成為小空閑分區(qū)。 實(shí)驗(yàn)中內(nèi)存分配的算法采用“最優(yōu)適應(yīng)”算法,即選擇一個能滿足要求的最小空閑分區(qū)。第三,在設(shè)計的數(shù)據(jù)表格基礎(chǔ)上設(shè)計內(nèi)存回收問題。內(nèi)存回收時若相鄰有空閑分區(qū)則合并空閑區(qū),修改空閑區(qū)表。 四、參考程序 #define n 10 //假定系統(tǒng)允許的最大作業(yè)數(shù)量為n #define m 10 //假定系統(tǒng)允許的空閑區(qū)最大為m #define minisize 100 struct { float address;//已分分區(qū)起始地址 float length;//已分分區(qū)長度、單位為字節(jié) int flag;//已分分區(qū)表登記欄標(biāo)志,“0”表示空欄目,實(shí)驗(yàn)中只支持一個字符的作業(yè)名 }used_table[n];//已分分區(qū)表 struct { float address;//空閑區(qū)起始地址 float length;//空閑區(qū)長度、單位為字節(jié) int flag;//空閑區(qū)表登記欄標(biāo)志,“0”表示空欄目,“1”表示未分配 }used_table[n];//空閑區(qū)表 allocate(J,xk)//采用最優(yōu)分配算法分配xk大小的空間 char J;float xk;{int i,k;float ad;k=-1;for(i=0;i //找到可用空閑區(qū),開始分配;若空閑區(qū)大小與要求分配的空間差小于minisize大小,則空閑區(qū)全部分配; //若空閑區(qū)大小與要求分配的空間差大于minisize大小,則從空閑區(qū)劃分一部分分配 if(free_table[k].length-xk<=minisize){free_table[k].flag=0;ad=free_table[k].address; 第2頁 xk=free_table[k].length;} else {free_table[k].length=free_table[k].length-xk;ad=free_table[k].address+free_table[k].length;} //修改已分配區(qū)表 i=0;while(used_table[i].flag!=0&&i reclaim(J)//回收作業(yè)名為J的作業(yè)所占的內(nèi)存空間 char J: {int i,k,j,s,t;float S,L;//尋找已分分區(qū)表中對應(yīng)的登記項(xiàng) S=0;while((used_table[S].flag!=J||used_table[S].flag==0)&&S used_table[S].flag=0;//取得歸還分區(qū)的起始地址S和長度L S=used_table[S].address;L=used_table[S].length;j=-1;k=-1;i=0; 第3頁 //尋找回收分區(qū)的上下鄰空閑區(qū),上鄰表目K,下鄰表目J while(i {free_table[k].length=free_table[j].length+free_table[k].length+L;free_table[j].flag+0;} else //上鄰空閑區(qū),下鄰非空閑區(qū),與上鄰合并 free_table[k].length=free_table[k].length+L;else if(j!=-1)//上鄰非空閑區(qū),下鄰空閑區(qū),與下鄰合并 {free_table[j].address=S;free_table[j].length=free_table[j].length+L;} else { //上下鄰均為非空閑區(qū),回收區(qū)域直接填入 t=0;//在空閑區(qū)表中尋找空欄目 while(free_table[t].flag==1&&t {printf(“內(nèi)存空閑表沒有空間,回收空間失敗n”);used_table[S].flag=J;return;} free_table[t].address=s;free_table[t].length=l;free_table[t].flag=1;} return(true);} //內(nèi)存回收函數(shù)結(jié)束 main(){ int i,a;float xk;char J;//空閑區(qū)表初始化 free_table[0].address=10240; 第4頁 free_table[0].length=102400;free_table[0].flag=1;for(i=1;i case 1;//a=1 分配內(nèi)存空間 printf(“輸入作業(yè)名J和作業(yè)所需長度XK:”);scanf(“%c%c%f”,&j,&xk);allocate(j,xk);//分配內(nèi)存空間 break;case 2;//a=2 回收內(nèi)存空間 printf(“輸入要回放分區(qū)的作業(yè)名”);scanf(“%c%c”,&j);reclaim(j);//回收內(nèi)存空間 break;case 3;//a=3顯示內(nèi)存情況,輸出空閑區(qū)表和已分分區(qū)表 printf(“輸出空閑區(qū)表:n起始地址 分區(qū)長度 標(biāo)志n”);for(i=0;i 第5頁 一.實(shí)驗(yàn)?zāi)康?/p> 通過編寫和調(diào)試存儲管理的模擬程序以加深對存儲管理方案的理解,熟悉可變分區(qū)存儲管理的內(nèi)存分配和回收。二.實(shí)驗(yàn)內(nèi)容 1.確定內(nèi)存空間分配表; 2.采用最優(yōu)適應(yīng)算法完成內(nèi)存空間的分配和回收; 3.編寫主函數(shù)對所做工作進(jìn)行測試。三.實(shí)驗(yàn)背景材料 由于可變分區(qū)的大小是由作業(yè)需求量決定的,故分區(qū)的長度是預(yù)先不固定的,且分區(qū)的個數(shù)也隨內(nèi)存分配和回收變動??傊蟹謪^(qū)情況隨時可能發(fā)生變化,數(shù)據(jù)表格的設(shè)計必須和這個特點(diǎn)相適應(yīng)。由于分區(qū)長度不同,因此設(shè)計的表格應(yīng)該包括分區(qū)在內(nèi)存中的起始地址和長度。由于分配時空閑區(qū)有時會變成兩個分區(qū):空閑區(qū)和已分分區(qū),回收內(nèi)存分區(qū)時,可能會合并空閑分區(qū),這樣如果整個內(nèi)存采用一張表格記錄己分分區(qū)和空閑區(qū),就會使表格操作繁瑣。分配內(nèi)存時查找空閑區(qū)進(jìn)行分配,然后填寫己分配區(qū)表,主要操作在空閑區(qū);某個作業(yè)執(zhí)行完后,將該分區(qū)變成空閑區(qū),并將其與相鄰的空閑區(qū)合并,主要操作也在空閑區(qū)。由此可見,內(nèi)存的分配和回收主要是對空閑區(qū)的操作。這樣為了便于對內(nèi)存空間的分配和回收,就建立兩張分區(qū)表記錄內(nèi)存使用情況,一張表格記錄作業(yè)占用分區(qū)的“己分分區(qū)表”;一張是記錄空閑區(qū)的“空閑區(qū)表”。這兩張表的實(shí)現(xiàn)方法一般有兩種:一種是鏈表形式,一種是順序表形式。在實(shí)驗(yàn)中,采用順序表形式,用數(shù)組模擬。由于順序表的長度必須提前固定,所以無論是“已分分區(qū)表”還是“空閑區(qū)表”都必須事先確定長度。它們的長度必須是系統(tǒng)可能的最大項(xiàng)數(shù)。 “已分分區(qū)表”的結(jié)構(gòu)定義 #define n 10 //假定系統(tǒng)允許的最大作業(yè)數(shù)量為n struct { float address;//已分分區(qū)起始地址 float length;//已分分區(qū)長度、單位為字節(jié) int flag;//已分分區(qū)表登記欄標(biāo)志,“0”表示空欄目,實(shí)驗(yàn)中只支持一個字符的作業(yè)名 }used_table[n];//已分分區(qū)表 “空閑區(qū)表”的結(jié)構(gòu)定義 #define m 10 //假定系統(tǒng)允許的空閑區(qū)最大為m struct { float address;//空閑區(qū)起始地址 float length;//空閑區(qū)長度、單位為字節(jié) int flag;//空閑區(qū)表登記欄標(biāo)志,“0”表示空欄目,“1”表示未分配 }used_table[n];//空閑區(qū)表 第二,在設(shè)計的數(shù)據(jù)表格基礎(chǔ)上設(shè)計內(nèi)存分配。 裝入一個作業(yè)時,從空閑區(qū)表中查找滿足作業(yè)長度的未分配區(qū),如大于作業(yè),空閑區(qū)劃分成兩個分區(qū),一個給作業(yè),一個成為小空閑分區(qū)。 實(shí)驗(yàn)中內(nèi)存分配的算法采用“最優(yōu)適應(yīng)”算法,即選擇一個能滿足要求的最小空閑分區(qū)。第三,在設(shè)計的數(shù)據(jù)表格基礎(chǔ)上設(shè)計內(nèi)存回收問題。內(nèi)存回收時若相鄰有空閑分區(qū)則合并空閑區(qū),修改空閑區(qū)表。 第1頁 四、參考程序 #define n 10 //假定系統(tǒng)允許的最大作業(yè)數(shù)量為n #define m 10 //假定系統(tǒng)允許的空閑區(qū)最大為m #define minisize 100 struct { float address;//已分分區(qū)起始地址 float length;//已分分區(qū)長度、單位為字節(jié) int flag;//已分分區(qū)表登記欄標(biāo)志,“0”表示空欄目,實(shí)驗(yàn)中只支持一個字符的作業(yè)名 }used_table[n];//已分分區(qū)表 struct { float address;//空閑區(qū)起始地址 float length;//空閑區(qū)長度、單位為字節(jié) int flag;//空閑區(qū)表登記欄標(biāo)志,“0”表示空欄目,“1”表示未分配 }used_table[n];//空閑區(qū)表 allocate(J,xk)//采用最優(yōu)分配算法分配xk大小的空間 char J;float xk;{int i,k;float ad;k=-1;for(i=0;i //找到可用空閑區(qū),開始分配;若空閑區(qū)大小與要求分配的空間差小于minisize大小,則空閑區(qū)全部分配; //若空閑區(qū)大小與要求分配的空間差大于minisize大小,則從空閑區(qū)劃分一部分分配 if(free_table[k].length-xk<=minisize){free_table[k].flag=0;ad=free_table[k].address;xk=free_table[k].length;} else {free_table[k].length=free_table[k].length-xk;ad=free_table[k].address+free_table[k].length; 第2頁 } //修改已分配區(qū)表 i=0;while(used_table[i].flag!=0&&i reclaim(J)//回收作業(yè)名為J的作業(yè)所占的內(nèi)存空間 char J: {int i,k,j,s,t;float S,L;//尋找已分分區(qū)表中對應(yīng)的登記項(xiàng) S=0;while((used_table[S].flag!=J||used_table[S].flag==0)&&S used_table[S].flag=0;//取得歸還分區(qū)的起始地址S和長度L S=used_table[S].address;L=used_table[S].length;j=-1;k=-1;i=0;//尋找回收分區(qū)的上下鄰空閑區(qū),上鄰表目K,下鄰表目J while(i 第3頁 } i++;} if(k!=-1)if(j!=-1)//上鄰空閑區(qū),下鄰空閑區(qū),三項(xiàng)合并 {free_table[k].length=free_table[j].length+free_table[k].length+L;free_table[j].flag+0;} else //上鄰空閑區(qū),下鄰非空閑區(qū),與上鄰合并 free_table[k].length=free_table[k].length+L;else if(j!=-1)//上鄰非空閑區(qū),下鄰空閑區(qū),與下鄰合并 {free_table[j].address=S;free_table[j].length=free_table[j].length+L;} else { //上下鄰均為非空閑區(qū),回收區(qū)域直接填入 t=0;//在空閑區(qū)表中尋找空欄目 while(free_table[t].flag==1&&t {printf(“內(nèi)存空閑表沒有空間,回收空間失敗n”);used_table[S].flag=J;return;} free_table[t].address=s;free_table[t].length=l;free_table[t].flag=1;} return(true);} //內(nèi)存回收函數(shù)結(jié)束 main(){ int i,a;float xk;char J;//空閑區(qū)表初始化 free_table[0].address=10240;free_table[0].length=102400;free_table[0].flag=1;for(i=1;i 第4頁 for(i=1;i case 1;//a=1 分配內(nèi)存空間 printf(“輸入作業(yè)名J和作業(yè)所需長度XK:”);scanf(“%c%c%f”,&j,&xk);allocate(j,xk);//分配內(nèi)存空間 break;case 2;//a=2 回收內(nèi)存空間 printf(“輸入要回放分區(qū)的作業(yè)名”);scanf(“%c%c”,&j);reclaim(j);//回收內(nèi)存空間 第5頁 計算機(jī)操作系統(tǒng) 實(shí)驗(yàn)報告 實(shí)驗(yàn)二 實(shí)驗(yàn)題目:存儲器管理 系別:計算機(jī)科學(xué)與技術(shù)系 班級: 姓名: 學(xué)號:2 一、實(shí)驗(yàn)?zāi)康?/p> 深入理解動態(tài)分區(qū)存儲管理方式下的內(nèi)存空間的分配與回收。 二、實(shí)驗(yàn)內(nèi)容 編寫程序完成動態(tài)分區(qū)存儲管理方式下的內(nèi)存分配和回收的實(shí)現(xiàn)。具體內(nèi)容包括: 確定用來管理內(nèi)存當(dāng)前使用情況的數(shù)據(jù)結(jié)構(gòu); 采用首次適應(yīng)算法完成內(nèi)存空間的分配; 分情況對作業(yè)進(jìn)行回收; 編寫主函數(shù)對所做工作進(jìn)行測試。 三、實(shí)驗(yàn)原理 分配:動態(tài)分區(qū)存儲管理方式把內(nèi)存除OS占用區(qū)域外的空間看作一個大的空閑區(qū)。當(dāng)作業(yè)要求裝入內(nèi)存時,根據(jù)作業(yè)需要內(nèi)存空間的大小查詢內(nèi)存中各個空閑區(qū),當(dāng)從內(nèi)存中找到一個大于或等于該作業(yè)大小的內(nèi)存空閑區(qū)時,選擇其中一個空閑區(qū),按作業(yè)要求劃出一個分區(qū)裝入該作業(yè)。 回收:作業(yè)執(zhí)行完后,它所占用的內(nèi)存空間被收回,成為一個空閑區(qū)。如果該空閑區(qū)的相鄰分區(qū)也是空閑區(qū),則需要將相鄰空閑區(qū)合并成一個空閑區(qū)。 四、實(shí)驗(yàn)方法 實(shí)現(xiàn)動態(tài)分區(qū)的分配與回收,主要考慮三個問題: 第一、設(shè)計記錄內(nèi)存使用情況的數(shù)據(jù)表格,用來記錄空閑區(qū)和作業(yè)占用的區(qū)域(利用結(jié)構(gòu)體類型數(shù)組來保存數(shù)據(jù)); 第二、在設(shè)計的數(shù)據(jù)表格基礎(chǔ)上設(shè)計內(nèi)存分配算法(采用首次適應(yīng)算法找合適的分區(qū)(對空閑分區(qū)表進(jìn)行排序),分配時要考慮碎片問題); 第三、在設(shè)計的數(shù)據(jù)表格基礎(chǔ)上設(shè)計內(nèi)存回收算法(分四種情況進(jìn)行回收(上鄰、下鄰、上下鄰和無相鄰分區(qū))。 五、實(shí)驗(yàn)步驟 第一,設(shè)計記錄內(nèi)存使用情況的數(shù)據(jù)表格 ? 已分配分區(qū)表:起始地址、長度、標(biāo)志(0表示“空表項(xiàng)”,1表示“已分配”)? 空閑分區(qū)表: 起始地址、長度、標(biāo)志(0表示“空表項(xiàng)”,1表示“未分配”) struct used_table { float address; //已分分區(qū)起始地址 float length; //已分分區(qū)長度,單位為字節(jié) int flag; //已分配表區(qū)登記欄標(biāo)志,用0表示空欄目,char zuoyename;}; //已分配區(qū)表 Struct free_table[ { float address; //空閑分區(qū)起始地址 float length; //空閑分區(qū)長度,單位為字節(jié) int flag; //空閑分區(qū)表登記欄目用0表示空欄目,1表示未配 };//空閑分區(qū)表 第二,在設(shè)計的表格上進(jìn)行內(nèi)存分配 ? 首次適應(yīng)算法:為作業(yè)分配內(nèi)存,要求每次找到一個起始地址最小的適合作業(yè)的分區(qū)(按起始地址遞增排序)。 ? 最大碎片size:要求當(dāng)找到的空閑分區(qū)-作業(yè)的大小的值小于或等于size時,將該分區(qū)全部分配給作業(yè)(數(shù)組后面元素向前移); ? 否則,給作業(yè)分割出一部分空間時,其余部分仍作為新的空閑分區(qū)登記(空閑分區(qū)長度=空閑分區(qū)長度-作業(yè)長度, ? 空閑分區(qū)起始地址=空閑分區(qū)起始地址+作業(yè)長度 第三,在設(shè)計的表格上進(jìn)行內(nèi)存回收。 1、上鄰:條件:回收作業(yè)的始址=某個空閑區(qū)的始址+長度 操作:空閑區(qū)的長度=空閑區(qū)的長度+作業(yè)的大小 2、下鄰:條件:回收作業(yè)的始址+作業(yè)的長度=某個空閑區(qū)的始址 操作: 空閑區(qū)的始址=回收作業(yè)的始址 空閑區(qū)的長度=空閑區(qū)的長度+作業(yè)的長度 3、上下鄰:條件:1,2條件同時成立 操作:空閑區(qū)的始址=上鄰的始址 空閑區(qū)的長度=上鄰的長度+作業(yè)的長度+下鄰的長度 刪除下鄰 4、無上下鄰: 操作:找flag=0的行 空閑區(qū)的始址=回收作業(yè)的始址 空閑區(qū)的長度=作業(yè)的長度 六、實(shí)驗(yàn)代碼 # include #define SADDRESS 200 //空閑分區(qū)初始的起始地址 #define SLENGTH 150000 //空閑分區(qū)的初始長度 struct used_t{ float address;//已分分區(qū)起始地址 float length;//已分分區(qū)長度 int flag;//已分配表區(qū)登記欄標(biāo)志,用0表示空欄目 }used_table[N];struct free_t{ float address;//空閑分區(qū)起始地址 float length;//空閑分區(qū)長度 int flag;//空閑分區(qū)表登記欄目用0表示空欄目,1表示未分配 }free_table[M];//空閑分區(qū)表 void allocate(char,float);//分配算法子程序 void reclaim(char);//回收算法子程序 void main(){ int i,a;float zyl;char zyn;//空閑分區(qū)表初始化 free_table[0].address=SADDRESS;//空閑分區(qū)表的起始地址 free_table[0].length=SLENGTH;//空閑分區(qū)表的長度 free_table[0].flag=1;//標(biāo)志位置1表示未分配 for(i=1;i free_table[i].length=0; free_table[i].flag=0;} //0表示空欄目 //已分分區(qū)表初始化 for(i=0;i used_table[i].length=0; used_table[i].flag=0;} while(1){cout<<“請選擇功能項(xiàng):”< <<“1-分配主存”< <<“2-回收主存”< <<“3-顯示主存”< <<“0-退出”< <<“選擇功能項(xiàng)(0-3):”; cin>>a;switch(a){case 0: //當(dāng)選擇0時退出程序 return; case 1: { //a=1 分配主存空間 cout<<“n請輸入作業(yè)名zyn和作業(yè)所需長度zyl(作業(yè)名為一個字符,長度zyl要小于”< cin>>zyn>>zyl; allocate(zyn,zyl);//為作業(yè)zyn分配主存空間 break; } case 2:{ // a=2 回收主存空間 cout<<“n請輸入要回收分區(qū)的作業(yè)名:”; cin>>zyn; reclaim(zyn);//回收作業(yè)zyn的主存空間 break;} case 3: { //a=3 顯示主存情況,輸出空閑區(qū)表和已分配區(qū)表 cout<<“n輸出空閑區(qū)表:”< <<“ 起始地址 分區(qū)長度 標(biāo)志”< for(i=0;i if(free_table[i].flag!=0)cout< cin.get(); cout<<“n輸出已分配區(qū)表:”< <<“ 起始地址 分區(qū)長度 標(biāo)志”< for(i=0;i cout< < break;} default:{ cout<<“n沒有該選項(xiàng)!”< break; }}} cin.get()}//分配算法子程序 void allocate(char zyn,float zyl){ float ad;int k=-1;int i=0;while(i if(free_table[i].length>=zyl&&free_table[i].flag==1) k=i; i++;} if(k==-1){ //未找到可用空閑區(qū),返回 cout<<“無可用空閑區(qū)!”< return;} /*找到可用空閑區(qū),開始分配:若空閑區(qū)大小與作業(yè)要求分配的空間差小于MIN,則將找到的空閑區(qū)全部分配給該作業(yè);若空閑區(qū)大小與要求分配的空間的差大于minisize,則從空閑區(qū)劃出一部分分配給作業(yè)。*/ if(free_table[k].length-zyl<=MIN){ free_table[k].flag=0;ad=free_table[k].address;zyl=free_table[k].length;for(i=k;i free_table[i]=free_table[i+1];} else{ free_table[k].length=free_table[k].length-zyl;ad=free_table[k].address;free_table[k].address=free_table[k].address+zyl;} /*修改已分配區(qū)表*/ i=0;while(used_table[i].flag!=0&&i s++;//找到作業(yè)zyn在以分配表中的表目s if(s>=N){ cout<<“找不到該作業(yè)!”< S=used_table[s].address;//取作業(yè)zyn在內(nèi)存中的首地址 L=used_table[s].length;//取作業(yè)zyn所分配到的內(nèi)存的長度 j=-1;k=-1;i=0;//尋找回收分區(qū)的上下鄰空閑區(qū),上鄰表目k,下鄰表目j while(i if(free_table[i].address==S+L)j=i;} i++;} if(k!=-1){ //有上鄰空閑區(qū) if(j!=-1){ //有下鄰空閑區(qū) 即有上下鄰空閑區(qū),三項(xiàng)合并 free_table[k].length=free_table[k].length+free_table[j].length+L; free_table[j].flag=0;} else //上鄰空閑區(qū),下鄰非空閑區(qū),與上鄰合并 free_table[k].length=free_table[k].length+L;}//if else { //k==-1 無上鄰空閑區(qū) if(j!=-1){ //無上鄰空閑區(qū),有下鄰空閑區(qū),與下鄰合并 free_table[j].address=S;free_table[j].length=free_table[j].length+L;} else{ //j==-1 上下鄰均為非空閑區(qū),回收區(qū)域直接填入 t=0;//在空閑區(qū)表中尋找空欄目 while(free_table[t].flag==1&&t cout<<“主存空閑表沒有空間,回收失??!”< return; } free_table[t].address=S; free_table[t].length=L; free_table[t].flag=1;}} for(i=0;i<=M-1;i++)for(int j=i;j 七、實(shí)驗(yàn)結(jié)果 1、總的存儲空間 2、分配空間 3、回收空間(1)有上下鄰 (2)有上鄰 (3)有下鄰 (4)無上下鄰,回收7 八、實(shí)驗(yàn)總結(jié) 1、通過實(shí)驗(yàn)學(xué)會了理解動態(tài)分區(qū)存儲管理方式下的內(nèi)存空間的分配與回收 2、學(xué)會了回收的四種方式 3、實(shí)驗(yàn)過程中遇到了問題,學(xué)會了與同學(xué)探討解決第二篇:可變分區(qū)存儲管理方式的內(nèi)存分配和回收
第三篇:可變分區(qū)存儲管理方式的內(nèi)存分配和回收實(shí)驗(yàn)報告
第四篇:可變分區(qū)存儲管理方式的內(nèi)存分配和回收實(shí)驗(yàn)報告(最優(yōu)算法)
第五篇:計算機(jī)操作系統(tǒng)動態(tài)分區(qū)存儲管理方式下的內(nèi)存空間的分配與回收實(shí)驗(yàn)報告