操作系統-在可變分區管理方式下采用最先適應算法實現主存分配和實現主存回收。

實驗五
一、實驗題目
在可變分區管理方式下采用最先適應算法實現主存分配和實現主存回收。
二、實驗內容
可變分區方式是按作業需要的主存空間大小來分割分區的。當要裝入一個作業時,根據作業需要的主存量查看是否有足夠的空閒空間,若有,則按需要量分割一個分區分配給該作業;若無,則作業不能裝入。隨着作業的裝入、撤離,主存空間被分成許多個分區,有的分區被作業佔用,而有的分區是空閒的。例如:
在這裏插入圖片描述
爲了說明哪些區是空閒的,可以用來裝入新作業,必須要有一張空閒區說明表,格式如下:
在這裏插入圖片描述
其中,起址——指出一個空閒區的主存起始地址。
長度——指出從起始地址開始的一個連續空閒的長度。
狀態——有兩種狀態,一種是“未分配”狀態,指出對應的由起址指出的某個長度的區域是空閒區;另一種是“空表目”狀態,表示表中對應的登記項目是空白(無效),可用來登記新的空閒區(例如,作業撤離後,它所佔的區域就成了空閒區,應找一個“空表目”欄登記歸還區的起址和長度且修改狀態)。由於分區的個數不定,所以空閒區說明表中應有適量的狀態爲“空表目”的登記欄目,否則造成表格“溢出”無法登記。
上述的這張說明表的登記情況是按提示(1)中的例所裝入的三個作業佔用的主存區域後填寫的。

(2) 當有一個新作業要求裝入主存時,必須查空閒區說明表,從中找出一個足夠大的空閒區。有時找到的空閒區可能大於作業需要量,這時應把原來的空閒區變成兩部分:一部分分給作業佔用;另一部分又成爲一個較小的空閒區。爲了儘量減少由於分割造成的空閒區,而儘量保存高地址部分有較大的連續空閒區域,以利於大型作業的裝入。爲此,在空閒區說明表中,把每個空閒區按其地址順序登記,即每個後繼的空閒區其起始地址總是比前者大。爲了方便查找還可使表格“緊縮”,總是讓“空表目”欄集中在表格的後部。
(3) 採用最先適應算法(順序分配算法)分配主存空間。
按照作業的需要量,查空閒區說明表,順序查看登記欄,找到第一個能滿足要求的空閒區。當空閒區大於需要量時,一部分用來裝入作業,另一部分仍爲空閒區登記在空閒區說明表中。
由於本實驗是模擬主存的分配,所以把主存區分配給作業後並不實際啓動裝入程序裝入作業,而用輸出“分配情況”來代替。最先適應分配算法如圖4-1。
(4) 當一個作業執行結束撤離時,作業所佔的區域應該歸還,歸還的區域如果與其它空閒區相鄰,則應合成一個較大的空閒區,登記在空閒區說明表中。例如,在提示(1)中列舉的情況下,如果作業2撤離,歸還所佔主存區域時,應與上、下相鄰的空閒區一起合成一個大的空閒區登記在空閒區說明表中。歸還主存時的回收算法如圖4-2。
(5) 請按最先適應算法設計主存分配和回收的程序。然後按(1)中假設主存中已裝入三個作業,且形成兩個空閒區,確定空閒區說明表的初值。現有一個需要主存量爲6K的作業4申請裝入主存;然後作業3撤離;再作業2撤離。請你爲它們進行主存分配和回收,把空閒區說明表的初值以及每次分配或回收後的變化顯示出來或打印出來。
三、實驗過程
1、實驗原理
最先適應算法分配主存空間是按照作業的需要量,查空閒分區表,順序查看長度欄,找到第一個能滿足要求的空閒區。當空閒區大於需要量時,一部分用來裝入作業,另一部分在空閒分區表中仍爲空閒區。
當一個作業執行結束撤離時,作業所佔的區域應該歸還,歸還的區域如果與其它空閒區相鄰,則應合成一個較大的空閒區,登記在空閒分區表中。
2、數據結構
作業進入內存:
根據作業大小,使用最先適應算法,從低地址空閒分區中依次判斷是否有滿足作業大小的空閒分區,若有則分配內存,修改空閒分區表,若無則不分配內存,提示沒有合適空間,最後都輸出空閒分區表情況。
作業撤出內存:
根據作業起始地址和大小,判斷該作業上下是否相鄰空閒分區,若只有上鄰空閒分區,則釋放內存後與其上鄰空閒分區合併,若只有下鄰空閒分區,則釋放內存後與其下鄰空閒分區合併,若上下都相鄰空閒分區,則釋放內存後與其上、下鄰空閒分區都合併,若不相鄰空閒分區,則釋放內存後在空閒分區表內單獨形成一個分區,最後輸出空閒分區表情況。
3、算法設計
struct free
{
int start; ///空閒分區始址
int size; ///空閒分區長度
int state; ///標誌位,1表示未分配,0表示分空表目
};
free free[N]={{14,12,1},{32,96,1},{128,120,0}};///初始化空閒分區

void setfree(int start,int size)
{
int flag1=0,flag2=0,flag3=0; ///flag1:表示回收區是否有下鄰空閒區; flag2:表示回收區是否有上下鄰空閒區; flag3:表示回收區是否有上鄰空閒區;
int i,j;
for(i=0;i<N;i++)
{
if(free[i].start= =start+size && free[i].state= =1) ///回收區有下鄰空閒區
{
size=size+free[i].size; ///向下合併空閒區
flag1=1;
for(j=0;j<N;j++)
if(free[j].start+free[j].size= =start && free[j].state= =1)
{
free[i].state=0;
free[i].start=free[N-1].start+free[N-1].size;
free[i].size=120;
free[j].size=free[j].size+size; ///向上合併空閒區
flag2=1; ///回收區有上下鄰空閒區
break;
}
if(flag2= =0) ///回收區無上鄰空閒區
{
free[i].start=start;
free[i].size=size;
break;
}
}
}
if(flag1= =0) ///回收區無下鄰空閒區,檢查其是否有上鄰空閒區
{
for(i=0;i<N;i++)
if(free[i].start+free[i].size= =start && free[i].state= =1)
{
free[i].size=free[i].size +size;
flag3=1;
break;
}
if(flag3= =0) ///回收區無上鄰空閒區
for(j=0;j<N;j++)
if(free[j].state= =0) ///將釋放區放入空表目中
{
free[j].start=start;
free[j].size=size;
free[j].state=1;
break;
}
}
}
四、實驗結果
在這裏插入圖片描述
五、體會與收穫
通過本次操作系統實驗,首先我的編程能力有了很大的提高,其次我對操作系統內存的分配,存儲空間的回收都有了全新的認識和深刻的理解。
在這次操作系統課程設計中我使用了C語言編寫程序,模擬在可變分區管理方式下采用最先適應算法實現主存分配與回收,通過自己動手編程和測試程序,讓我對可變分區管理方式的原理理解的更加透徹,模擬過程中,也讓我發現了自己以前的很多誤區,修改程序的工程中再一次鞏固了所學知識。
六、源代碼
#include <stdio.h>
#include <String.h>
#define N 3 ///空閒區和空表目總塊數

struct free
{
int start; ///空閒分區始址
int size; ///空閒分區長度
int state; ///標誌位,1表示未分配,0表示分空表目
};
free free[N]={{14,12,1},{32,96,1},{128,120,0}};///初始化空閒分區

///給作業分配主存空間函數
int alloc(int n) ///爲作業分配內存,滿足返回1,不滿足返回0
{
int i,flag=0; ///用來標識是否有滿足作業的空閒空間,1表示有,0表示無
for(i=0;i<N;i++)
{
if(free[i].state= =1 && free[i].size>n)///空閒區空間大於作業需求
{
free[i].start=free[i].start+n;
free[i].size=free[i].size-n;
flag=1;
return 1;
}
if(free[i].state= =1 && free[i].size==n)///空閒分區剛好滿足作業需求
{
free[i].state=0; ///調整狀態位
flag=1;
return 1;
}

}
if(flag==0)
	return 0;

}

void setfree(int start,int size)
{
int flag1=0,flag2=0,flag3=0; ///flag1:表示回收區是否有下鄰空閒區; flag2:表示回收區是否有上下鄰空閒區; flag3:表示回收區是否有上鄰空閒區;
int i,j;
for(i=0;i<N;i++)
{
if(free[i].start= =start+size && free[i].state= =1) ///回收區有下鄰空閒區
{
size=size+free[i].size; ///向下合併空閒區
flag1=1;
for(j=0;j<N;j++)
if(free[j].start+free[j].size= =start && free[j].state= =1)
{
free[i].state=0;
free[i].start=free[N-1].start+free[N-1].size;
free[i].size=120;
free[j].size=free[j].size+size; ///向上合併空閒區
flag2=1; ///回收區有上下鄰空閒區
break;
}
if(flag2= =0) ///回收區無上鄰空閒區
{
free[i].start=start;
free[i].size=size;
break;
}
}
}
if(flag1= =0) ///回收區無下鄰空閒區,檢查其是否有上鄰空閒區
{
for(i=0;i<N;i++)
if(free[i].start+free[i].size= =start && free[i].state= =1)
{
free[i].size=free[i].size +size;
flag3=1;
break;
}
if(flag3= =0) ///回收區無上鄰空閒區
for(j=0;j<N;j++)
if(free[j].state= =0) ///將釋放區放入空表目中
{
free[j].start=start;
free[j].size=size;
free[j].state=1;
break;
}
}
}
///對空閒分區表按地址順序排序
void sort()
{
int i,j;
struct free f; //中間變量
for(i=0;i<N;i++) //將空閒區按始地址順序在表中排列
for(j=0;j<N-1;j++)
if(free[j].start>free[j+1].start)
{
f=free[j];
free[j]=free[j+1];
free[j+1]=f;
}
for(i=0;i<N;i++) ///將空表目放在表後面
for(j=0;j<N-1;j++)
if(free[j].state= =0 && free[j+1].state==1)
{
f=free[j];
free[j]=free[j+1];
free[j+1]=f;
}
}

int main(void)
{
int i,flag;
///打印初始分區表
printf("\n初始空閒分區表爲:\n");
sort();
printf(" | 起址 | 長度 | 狀態 | \n");
for(i=0;i<N;i++)
{
printf(" |%8d |%8d |%8d | \n",free[i].start,free[i].size,free[i].state);
}
///作業四調入內存
printf("\n大小爲6K的作業四進入內存\n");
flag=alloc(6);
printf("\n經過分配後,空閒分配表爲:\n");
sort();
printf(" | 起址 | 長度 | 狀態 | \n");
for(i=0;i<N;i++)
{
printf(" |%8d |%8d |%8d | \n",free[i].start,free[i].size,free[i].state);
}
if(flag==0)
{
printf(“沒有合適的空閒區,請等待!”);
}
///作業三撤離
printf("\n起始地址爲10,大小爲4的作業三撤離\n");
setfree(10,4);
printf("\n作業三內存釋放後,空閒分配表爲:\n");
sort();
printf(" | 起址 | 長度 | 狀態 | \n");
for(i=0;i<N;i++)
{
printf(" |%8d |%8d |%8d | \n",free[i].start,free[i].size,free[i].state);
}
///作業二撤離
printf("\n起始地址爲26,大小爲6的作業二撤離\n");
setfree(26,6);
printf("\n作業二內存釋放後,空閒分配表爲:\n");
sort();
printf(" | 起址 | 長度 | 狀態 | \n");
for(i=0;i<N;i++)
{
printf(" |%8d |%8d |%8d | \n",free[i].start,free[i].size,free[i].state);
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章