1. 實驗目的
可變分區分配是一種重要的存儲管理思想,目前流行的操作系統采用的分段存儲管理的基本思想就源自該方法。本實驗的目的是通過編程來模擬一個簡單的可變分區分配存儲管理系統,利用最先適應分配算法實現。經過實驗者親自動手編寫管理程序,可以進一步加深對可變分區分配存儲管理方案設計思想的理解。
2. 實驗原理
固定分區分配按操作系統初始化時划定的分區方案為作業分配內存,由於各分區的位置和大小固定,因此作業所需的內存大小通常小於分到的實際內存的大小,造成存儲空間的浪費。可變分區分配對此作了改進,它總是根據作業的實際需要分配剛好夠用的連續存儲空間,保證分配給作業的存儲空間都是有用的,避免了零頭的產生。
(1) 可變分區中的數據結構
建立描述作業的數據結構作業控制塊,至少應包括:
作業名稱
作業需要執行時間
作業的內存需求
作業調入主存時間
作業執行結束時間
作業所在分區的起始地址
建立描述內存已分配分區的數據結構;
建立描述內存未分配的空閑分區的數據結構;
空閑分區和已分配分區的信息可以使用分區表來描述。系統中所有空閑分區構成分區表,所有已分配分區構成分配分區表。
出於效率的考慮,也可使用分區鏈來記錄分區信息。分區鏈是一種雙向鏈表,鏈表的每個結點描述一個分區的信息。系統中所有空閑分區構成空閑分區鏈,所有已分配分區構成分配分區鏈。分配和回收分區時,需要在這兩個鏈表中進行結點的查找和插入、刪除與修改操作。為改進算法的執行效率,可以將分區鏈按特定的順序排序。
分區鏈結點的數據結構為:
Struct Section { Section *pPre; //前向指針,指向鏈表的前一個結點 int nSart; //分區的起始地址 int nSize; //分區的尺寸 Section *pSuf; //后向指針,指向鏈表的后一個結點 };
可變分區分配算法——最先適應分配算法
最先適應分配算法要求空閑分區按地址遞增的順序排列,在進行內存分配時,從低地址部分向高地址部分查找,直到找到一個能滿足要求的空閑分區為止。然后按作業實際大小,從該空閑區划出一塊空間給作業,剩下的繼續留在記錄空閑分區的數據結構中。
(1) 可變分區的回收算法
當作業運行完畢釋放內存時,系統首先根據回收分區的首地址,在分配分區表(鏈)中找到相應的分區結點,摘下該結點並插入空閑分區表(鏈),插入時應該根據插入點附近空閑分區的情況進行處理,主要有以下幾種情況:
回收區與插入點的前一分區相鄰接,將這兩個分區合並為一個;
回收區與插入點的后一分區相鄰接,將這兩個分區合並為一個;
回收區與插入點的前后分區均相鄰接,將這三個分區合並為一個;
回收區與插入點的前后分區均不鄰接,將這兩個分區合並為一個。
3. 實驗內容
(1)編程實現簡單的可變分區分配存儲管理系統。要求:
a) 建立描述作業和內存分區的數據結構。
b) 初始信息輸入,包括內存初始大小、各作業信息、使用哪種分區分配算法等。這些信息可以直接從鍵盤上輸入,也可以從文件讀取。
c) 程序實現最先適應分配算法,程序初始化或運行過程中都應能指定算法。
d) 編程實現分區回收算法,對實驗列出的幾種分區回收情況都應該能處理。
(2)使用本程序執行下面的一批作業,觀察內存的分配和回收情況。系統可用內存的大小為2560K。
作業號 |
到達時間 |
執行時間 |
要求執行時間 |
J1 |
0 |
15 |
600K |
J2 |
1 |
8 |
1000K |
J3 |
2 |
40 |
300K |
J4 |
3 |
30 |
700K |
J5 |
4 |
20 |
500K |
4. 實驗步驟
i. 選用合適的實驗程序開發環境。
ii. 設計程序結構,規划程序功能。
iii. 完成程序的編碼與測試。
iv. 設計實驗數據。
v. 針對實驗數據運行程序,並將結果記錄在實驗報告上。
5.實驗代碼:
#include "iostream" #include"stdlib.h" using namespace std; #define Free 0 // 空閑狀態 #define Busy 1 // 已分配狀態 #define OK 1 // 分配成功 #define ERROR 0 // 分配出錯 #define MAX_length 1024 // 最大內存空間為 1024 int flag; typedef struct freeSpace // 定義一個空閑區表結構 { long size; // 分區大小 long address; // 分區首地址 int state; // 分區分配狀態 }ElemType; // 線性表的雙向鏈表存儲結構 typedef struct DuLNode { ElemType data; struct DuLNode *prior; // 前趨指針 struct DuLNode *next; // 后繼指針 } DuLNode ,*DuLinkList; DuLinkList head_Node; // 頭結點 DuLinkList end_Node; // 尾結點 int alloc(int); // 內存分配選擇 int free(int); // 內存回收 int First_fit(int); // 首次適應算法 void show(); // 查看分配 int Initblock(); // 初始化空間表 int Initblock() // 初始化帶頭結點的內存空間 { head_Node=(DuLinkList)malloc(sizeof(DuLNode));// 動態分配頭節點內 end_Node=(DuLinkList)malloc(sizeof(DuLNode));// 動態分配尾節點內存 if(head_Node!=NULL)//動態內存申請成功 { head_Node->prior=NULL; // 頭結點的前驅指針指向空 head_Node->next=end_Node; // 頭結點的后繼指針指向尾 end_Node->prior=head_Node; // 尾結點的前驅指針指向頭 end_Node->next=NULL; // 尾結點的后繼指針指向空 end_Node->data.address=0; // 尾結點的地址是 0 end_Node->data.size=MAX_length; // 分區大小是最大分區 end_Node->data.state=Free; // 狀態是空 return OK; } else return ERROR; } //主函數 int main() { int ch; Initblock(); // 設置初始空間表 int choice; // 操作標記 while(1) { cout<<"\n1: 分配內存 \t2: 回收內存 \t3: 內存使用情況顯示 \t4: 退出\n\n"; cout<<" 請選擇您的操作: "; cin>>choice; if(choice==1) { alloc(ch); }// 分配內存 else if(choice==2) // 內存回收 { int flag; cout<<" 請輸入您要釋放的分區號: "; cin>>flag; free(flag); } else if(choice==3) show(); else if(choice==4) exit(0); // 退出 else // 輸入操作有誤 { cout<<" 輸入有誤,請重試 !"<<endl; continue; } } } // 分配主存 int alloc(int ch) { int need; cout<<"\n\n 請輸入需要分配的空間大小 :"; cin>>need; if(need<=0) { cout<<"\n\n 請重新輸入分配大小 !"<<endl; return ERROR; } if(First_fit(need)==OK)//調用首次適應算法 cout<<" 分配成功 !"<<endl; else cout<<" 內存不足,分配失敗 !"<<endl; return OK; } // 首次適應算法 int First_fit(int need) { DuLinkList temp=(DuLinkList)malloc(sizeof(DuLNode)); temp->data.size=need; // 設置新申請空間的大小 temp->data.state=Busy; // 設置新申請空間的狀態 DuLNode *p=head_Node->next; while(p) { if(p->data.state==Free && p->data.size==need) // 現有的空閑 { p->data.state=Busy; // 修改該空閑塊的狀態為已分配 return OK; break; } if(p->data.state==Free && p->data.size>need) // 現有的空閑 { temp->prior=p->prior; // 修改雙向鏈 temp->next=p; temp->data.address=p->data.address; p->prior->next=temp; p->prior=temp; p->data.address+=need;//修改剩余空閑區的首地址 p->data.size-=need;//修改剩余空閑區的大小 return OK; break; } p=p->next; } return ERROR; } // 回收算法 int free(int flag) { DuLNode *p=head_Node; for(int i= 0; i <= flag; i++) if(p!=NULL) p=p->next; else return ERROR; p->data.state=Free; if(p->prior!=head_Node && p->prior->data.state==Free)//與前面的空閑區相連 { p->prior->data.size+=p->data.size; p->prior->next=p->next; p->next->prior=p->prior; p=p->prior; } if(p->next!=end_Node && p->next->data.state==Free)// 與后面的空閑塊相連 { p->data.size+=p->next->data.size; p->next->next->prior=p; p->next=p->next->next; } if(p->next==end_Node && p->next->data.state==Free)// 與最后的空閑塊相連 { p->data.size+=p->next->data.size; p->next=NULL; } return OK; } // 顯示主存分配情況 void show() { int flag = 0; cout<<"\n\n 主存分配情況 :\n"; cout<<"++++++++++++++++++++++++++++++++++++++++++++++\n\n"; DuLNode *p=head_Node->next; cout<<" 分區號 \t 起始地址 \t 分區大小 \t 狀態\n\n"; while(p) { cout<<" "<<flag++<<"\t"; cout<<" "<<p->data.address<<"\t\t"; cout<<" "<<p->data.size<<"KB\t\t"; if(p->data.state==Free) cout<<" 空閑\n\n"; else cout<<" 已分配 \n\n"; p=p->next; } cout<<"++++++++++++++++++++++++++++++++++++++++++++++\n\n"; }