要求:
系統根據申請者的要求,按照一定的分配策略分析內存空間的使用情況,找出能滿足請求的空閑區,分給申請者;當程序執行完畢或主動歸還內存資源時,系統要收回它所占用的內存空間或它歸還的部分內存空間,主存分配算法使用最壞適應分配算法。
程序運行時根據文件內容初始化空閑區表,文件內容為每行兩項:起始地址 長度 中間以逗號隔開,文件內容如下:
10,313,417,230,838,7
可變分區存儲管理的內存分配方案一般采用"已分配區表"和"空閑區表"來記錄主存已分配和未分配的情況,本例中采用單向鏈表方式來表示兩種結構。
分配內存時:從"空閑區表"中找出一項能滿足申請空間的記錄,然后分割該項,如果分割出剩余空間,則將剩余空間重新放入"空閑區表"中,同時產生一個"已分配區記錄項",該記錄的長度為申請的空間大小,起始地址為分割的"空閑區"項的起始地址。并將該記錄插入到"已分配區表"中。
回收作業內存時:刪除該作業在"已分配區表"中的記錄項,并按該項的地址和長度創建一個"空閑區"記錄,遍歷"空閑區表",如果存在上邊界相鄰或者下邊界相鄰的記錄項,則合并兩者(無相鄰區塊,不需要做任何操作),最后將該記錄插入到"空閑區表"中,并使之滿足降序條件。
空閑區表數據結構:
//空閑區表struct free_link{ int saddr;//起始地址 int len;//長度 int flag;//標志 struct free_link *next;};已分配區表數據結構://已分配區表struct alloc_link{ int saddr;//起始地址 int len;//長度 int work;//作業名 struct alloc_link *next;};最壞適應分配算法:空閑區表中每個記錄項按照長度遞減的順序排列,當需要分配空間時,只需要從表中取出第一項,然后為任務分割空間即可,如果分割后有剩余空間則將剩余部分再次插入空閑區表中,并重新調整表中記錄項,使得滿足按照長度遞減順序。
分配內存流程圖:
內存回收流程圖:
在回收內存時,會涉及到回收的空閑塊可能會與"空閑區表"中的某個記錄項上邊界相鄰或者下邊界相鄰或者上下邊界都有相鄰的空閑塊,這時候就需要合并要回收的記錄塊和已有的空閑塊,本例中采用的方式是:先根據要回收的"已分配區表"中的記錄項A,生成一個地址和長度相同的空閑塊記錄B,然后遍歷"空閑區塊表",發現有上邊界相鄰的記錄項C,則修改B的起始地址為C記錄中的起始地址,長度為B塊的長度+C塊的長度,然后從鏈表中刪除記錄C,繼續遍歷,如果發現有下邊界相鄰的記錄D,則再修改C的長度為原有長度+D的記錄長度,從鏈表中再把記錄D刪除,這樣直到遍歷到鏈表尾部。此時4中不同情況都已經包含(上邊界相鄰、下邊界相鄰,上下邊界同時相鄰、無相鄰),只需要將記錄B插入到"空閑區表"中即可。
空閑塊合并核心代碼:
//空閑塊頭指針 fp = free_head; while(fp->next != NULL) { //上邊界相同 if((fp->next->saddr + fp->next->len) == fitem->saddr) { //上邊界與待回收的空間邊界進行合并 fitem->saddr = fp->next->saddr; fitem->len = fp->next->len + fitem->len; //釋放原有空閑塊的內存 tmp_item = fp->next; fp->next = tmp_item->next; tmp_item->next = NULL; free(tmp_item); tmp_item = NULL; } if((fitem->saddr + fitem->len) == fp->next->saddr) { //下邊界與待回收的空間邊界合并 fitem->len = fitem->len + fp->next->len; //釋放原有空閑塊內存 tmp_item = fp->next; fp->next = tmp_item->next; tmp_item->next = NULL; free(tmp_item); tmp_item = NULL; } //如果已經遍歷到鏈尾則跳出 if(fp->next == NULL) { break; } fp = fp->next; } //重新調整空閑區表,按空間遞減順序排列 fp = free_head; while(fp->next != NULL) { if(fp->next->len <= fitem->len) { break; } fp = fp->next; } fitem->next = fp->next; fp->next = fitem;空閑塊合并示意圖如下:
空閑區表和已分配區表在分配和回收過程中變化效果圖:
代碼示例
新聞熱點
疑難解答