1. 程式人生 > >利用C語言記憶體管理模擬實驗

利用C語言記憶體管理模擬實驗

模擬實現一個簡單的固定(可變)分割槽儲存管理系統

實驗內容

(1)建立相關的資料結構,作業控制塊、已分配分割槽及未分配分割槽
(2)實現一個分割槽分配演算法,如最先適應演算法、最優或最壞適應分配演算法
(3)實現一個分割槽回收演算法
(4)給定一個作業/程序,選擇一個分配或回收演算法,實現分割槽儲存的模擬管理

實驗步驟

首先,初始化函式initial()將分割槽表初始化並建立空閒分割槽列表,空閒區第一塊的長度是30,以後的每個塊長度比前一個的長度長20。
frees[0].length=30
第二塊的長度比第一塊長20,第三塊比第二塊長20,以此類推。
frees[i].length=frees[i-1].length+20;
下一塊空閒區的首地址是上一塊空閒區的首地址與上一塊空閒區長度的和。frees[i].front=frees[i-1].front+frees[i-1].length;
分配區的首地址和長度都初始化為零occupys[i].front=0;occupys[i].length=0;
顯示函式show()是顯示當前的空閒分割槽表和當前的已分配表的具體類容,分割槽的有起始地址、長度以及狀態,利用for語句迴圈輸出。有一定的格式,使得輸出比較美觀好看。
assign()函式是運用首次適應分配演算法進行分割槽,從鏈首開始順序查詢,直至找到一個大小能滿足要求的空閒分割槽為止;然後再按照作業的大小,從該分割槽中劃出一塊記憶體空間分配給請求者,餘下的空閒分割槽仍留在空閒鏈中。若從鏈首直至鏈尾都不能找到一個能滿足要求的分割槽,則此次記憶體分配失敗,返回。這個演算法傾向於優先利用記憶體中低址部分被的空閒分割槽,從而保留了高址部分的的大空閒區。著給為以後到達的大作業分配大的記憶體空間創造了條件。它的缺點是低地址部分不斷被劃分,會留下很多難以利用的、很小的空閒分割槽,而每次查詢又都是從低址部分開始,這樣無疑會增加查詢可用空閒分割槽的開銷。
分配記憶體,從空閒的分割槽表中找到所需大小的分割槽。設請求的分割槽的大小為job_length,表中每個空閒分割槽的大小可表示為free[i].length。如果frees[i].length>=job_length,即空閒空間I的長度大於等於作業的長度將空閒標誌位設定為1,如果不滿足這個條件則輸出:“對不起,當前沒有滿足你申請長度的空閒記憶體,請稍後再試!”。如果frees[i].length>=job_length空閒區空間I的長度不大於作業長度,I的值加1判斷下一個空閒區空間是否大於作業的長度。把未用的空閒空間的首地址付給已用空間的首地址,已用空間的長度為作業的長度,已用空間數量加1。如果(frees[i].length>job_length),空間的長度大於作業的長度,frees[i].front+=job_length; 空閒空間的起始首地址=原空閒區間的起始長度加作業長度frees[i].length-=job_length;空閒區間的長度=原空閒區間的長度-作業的長度。如果空間的長度與作業的長度相等,空閒區向前移一位,空閒區的數量也減一。這樣判斷所有情況並相應分配之後,記憶體空間分配成功。
第二個操作為:撤消相應作業。在這個操作中,進行了以下步驟:
(1)按照系統提示輸入將要撤消的作業名;
(2)判斷該作業是否存在
若不存在:輸出“沒有這個作業名,請重新輸入作業名”;
若存在:則先分別用flag,start,len儲存該作業在分配區表的位置i,記憶體空間的首地址以及長度。接著根據回收區的首地址,即該作業的首地址,從空閒區表中找到相應的插入點,將其加入空閒表,此時可能出現以下三種情況之一:
1 .回收區只與插入點前一個空閒分割槽F1相鄰接即(frees[i].front+frees[i].length)==start),此時判斷其是否與後一個空閒分割槽F2相鄰接,又分兩種情況:
若相鄰接,則將三個分割槽合併,修改新的空閒分割槽的首地址和長度。新的首地址為F1的首地址,長度為三個分割槽長度之和,相應的程式碼為:frees[i].length=frees[i].length+frees[i+1].length+len;,並相應的空閒區表。
若不相鄰接,即合併後的首應將回收區與插入點的前一分割槽合併,則不須為回收分割槽分配新的表項,只須修改其前一分割槽的大小。該大小為F1與當前作業大小之和。frees[i].length+=len;
2 .回收分割槽與插入點前一個空閒分割槽不鄰接但與後一空閒分割槽F2鄰接。此時應合併當前作業分割槽與F2分割槽,合併後的分割槽首地址為當前作業首地址start,長度為兩個分割槽長度之和。程式碼為:frees[i].front=start; frees[i].length+=len;
3.回收分割槽既不與插入點前一空閒分割槽相鄰接,也不與後一空閒分割槽相鄰接。此時只須將該回收分割槽插入空閒區表即可。此時空閒區的數量加1。
將回收區加入空閒區表後還須修改分配區表內容。具體為:修改分配區表中回收區(第一區)之後的各區指標,使其依次前移一位,即occupys[i]=occupys[i+1];同時已分配分割槽數量減1,即occupy_quantity–;
最後輸出記憶體空間回收完畢!即完成了撤消作業並回收相應空間的操作。

最後附上原始碼

#include<stdlib.h>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<iomanip>

const int MAXJOB=5;
typedef struct node
{
    int front;
    int length;
    char data[20];
}job;

job frees[MAXJOB];
int free_quantity;

job occupys[MAXJOB];
int occupy_quantity;

int
initial() { int i; frees[0].front =0; frees[0].length = 30; occupys[0].front = 0; occupys[0].length = 0; strcpy(frees[0].data,"free"); for(i=1;i<MAXJOB;i++) { frees[i].front = frees[i-1].front+frees[i-1].length; frees[i].length = frees[i-1].length+20; strcpy(frees[i].data,"free"
); occupys[i].front = 0; occupys[i].length = 0; strcpy(occupys[i].data,""); } free_quantity = MAXJOB; occupy_quantity = 0; return 1; } void assign(){ char job_name[20]; int job_length; int i,j,flag,t; printf("請輸入新申請記憶體空間的作業名和空間大小:"); scanf("%s",job_name); scanf("%d",&job_length); flag=0; for(i=0;i<free_quantity;i++) { if(frees[i].length>=job_length) { flag = 1; } } if(flag==0) { printf("對不起,當前沒有滿足你申請長度的空閒記憶體,請稍後再試!\n"); } else { t=0; i = 0; while(t==0) { if(frees[i].length>=job_length) { t=1; } i++; } i--; occupys[occupy_quantity].front = frees[i].front; strcpy(occupys[occupy_quantity].data,job_name); occupys[occupy_quantity].length = job_length; occupy_quantity++; if(frees[i].length>job_length) { frees[i].front+=job_length; frees[i].length-=job_length; } else { for(j=i;j<free_quantity-1;j++) { frees[j] = frees[j+1]; } free_quantity--; } printf("記憶體空間分配成功!\n"); } } void show(){ int i; printf("-----------------------------\n"); printf("當前空閒分割槽表如下:\n"); printf("起始地址 長度 狀態\n"); for(i=0;i<free_quantity;i++) { printf("%5d %8d %s\n",frees[i].front,frees[i].length,frees[i].data); } printf("-----------------------------\n"); printf("當前已分配表如下:\n"); printf("起始地址 長度 佔用作業名\n"); for(i=0;i<occupy_quantity;i++) { printf("%5d %6d %s\n",occupys[i].front,occupys[i].length,occupys[i].data); } printf("-----------------------------\n"); } void cancel(){ char job_name[20]; int i,j,flag,p=0; int start; int len; printf("請輸入要撤銷的作業名:"); scanf("%s",job_name); flag=0; for(i=0;i<occupy_quantity;i++){ if(!strcmp(occupys[i].data,job_name)) { flag=i; start=occupys[i].front; len=occupys[i].length; } } if(flag==0){ printf("沒有這個作業名,請重新輸入作業名!\n"); } else{ for(i=0;i<free_quantity;i++) { if((frees[i].front+frees[i].length)==start) { if(((i+1)<free_quantity)&&(frees[i+1].front==start+len)){ frees[i].length=frees[i].length+frees[i+1].length+len; for(j=i+1;j<free_quantity;j++){ frees[j]=frees[j+1]; } free_quantity--; p=1; } else{ frees[i].length+=len; p=1; } } if(frees[i].front==(start+len)) { frees[i].front=start; frees[i].length+=len; p=1; } } if(p==0){ frees[free_quantity].front=start; frees[free_quantity].length=len; free_quantity++; } for(i=flag;i<occupy_quantity;i++) { occupys[i]=occupys[i+1]; } occupy_quantity--; printf("記憶體空間回收完畢!\n"); } } void main(){ int flag=0; int t=1; int choice=0; printf("|-----------------------------|\n"); printf("| 可變分割槽儲存管理模擬系統 |\n"); printf("|-----------------------------|\n"); printf("|選單: (0)退出 |\n"); printf("| |\n"); printf("| (1)申請空間 (2)撤銷作業 |\n"); printf("| |\n"); printf("| (3)顯示空閒表和分配表 |\n"); printf("|-----------------------------|\n"); initial(); flag=initial(); while(flag==1) { printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); printf("請選擇:"); scanf("%d",&choice); switch(choice) { case 1: assign();break; case 2: cancel();break; case 3: show(); break; case 0: flag=0;break; default: printf("選擇錯誤!"); } } }

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述