一、實驗內容
主存儲器空間的分配和回收。
二、實驗目的
一個好的計算機系統不僅要有一個足夠容量的、存取速度高的、穩定可靠的主存儲器,而且要能合理地分配和使用這些存儲空間。當用戶提出申請存儲器空間時,存儲管理必須根據申請者的要求,按一定的策略分析主存空間的使用情況,找出足夠的空閑區域分配給申請者。當作業撤離或主動歸還主存資源時,則存儲管理要收回作業占用的主存空間或歸還部分主存空間。主存的分配和回收的實現雖與主存儲器的管理方式有關的,通過本實驗幫助學生理解在不同的存儲管理方式下應怎樣實現主存空間的分配和回收。
三、實驗題目
模擬在分頁式管理方式下采用位示圖來表示主存分配情況,實現主存空間的分配和回收。
[提示]:
(1) 分頁式存儲器把主存分成大小相等的若干塊,作業的信息也按塊的大小分頁,作業裝入主存時可把作業的信息按頁分散存放在主存的空閑塊中,為了說明主存中哪些塊已經被占用,哪些塊是尚未分配的空閑塊,可用一張位示圖來指出。位示圖可由若干存儲單元來構成,其中每一位與一個物理塊對應,用0/1表示對應塊為空閑/已占用。
(2) 假設某系統的主存被分成大小相等的64塊,則位示圖可用8個字節來構成,另用一單元記錄當前空閑塊數。如果已有第0,1,4,5,6,9,11,13,24,31,共10個主存塊被占用了,那么位示圖情況如下:
字 位 節 數 號 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
2 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
3 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
4 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
5 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
6 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
7 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
(3) 當要裝入一個作業時,根據作業對主存的需要量,先查當前空閑塊數是否能滿足作業要求,若不能滿足則輸出分配不成功。若能滿足,則查位示圖,找出為“0”的一些位,置上占用標志“1”,從“當前空閑塊數”中減去本次占用塊數。
按找到的計算出對應的塊號,其計算公式為:
塊號= j´8+i
其中,j表示找到的是第n個字節,I表示對應的是第n位。
根據分配給作業的塊號,為作業建立一張頁表,頁表格式:
頁 號 |
塊 號 |
0 |
|
1 |
|
2 |
|
M M
|
|
(4) 當一個作業執行結束,歸還主存時,根據該作業的頁表可以知道應歸還的塊號,由塊號可計算出在位示圖中的對應位置,把對應位的占用標志清成“0”,表示對應的塊已成為空閑塊。歸還的塊數加入到當前空閑塊數中。由塊號計算在位示圖中的位置的公式如下:
字節號 j=[塊號/8] ([ ]表示取整)
位數 i={塊號/8} ({ }表示取余)
(5) 設計實現主存分配和回收的程序。假定位示圖的初始狀態如(2)所述,現有一信息量為5頁的作業要裝入,運行你所設計的分配程序,為作業分配主存且建立頁表(格式如(3)所述)。然后假定有另一作業執行結束,它占用的塊號為第4,5,6和31塊,運行你所設計的回收程序,收回作業歸還的主存塊。
要求能顯示和打印分配或回收前后的位示圖和當前空閑塊數,對完成一次分配后還要顯示或打印為作業建立的頁表。
四、實驗報告
(1) 實驗題目。
(2) 程序中使用的數據結構及符號說明。
(3) 流程圖。
(4) 打印一份源程序並附上注釋。
(5) 打印程序運行時的初值和運行結果,要求如下:
打印位示圖和當前空閑塊數的初值;要求裝入的作業對主存的申請量,為作業分配后的位示圖、當前空閑塊數和頁表;作業歸還的塊號、回收作業所占主存后的位示圖和當前空閑塊數。
#include<stdio.h> #include<string.h> #include<malloc.h> #include"stdlib.h" struct work { int size; char name[10]; int a[64]; }; typedef struct node { struct work data; struct node* next; }Node;
int **table; int v=0; int kuaihao[10][64]; void menu() { printf("1.打印位視圖\n"); printf("2.添加作業\n"); printf("3.結束作業\n"); printf("4.顯示所有作業\n"); printf("5.退出\n"); } void Initial() { int i,j; table=(int **)malloc(sizeof(int)*8);//使用指針動態建立一個位視圖的數組 for(i=0;i<8;i++) { table[i]=(int *)malloc(sizeof(int)*8); } for(i=0;i<8;i++) { for(j=0;j<8;j++) { table[i][j]=0; } } table[0][0]=1,table[0][1]=1,table[0][4]=1,table[0][5]=1,table[0][6]=1; table[1][1]=1,table[1][3]=1,table[1][5]=1,table[3][0]=1,table[3][7]=1; } int kongxiankuai() { int k; int i,j; k=0; for(i=0;i<8;i++) { for(j=0;j<8;j++) { if(table[i][j]==0) { k++; } } } return k; } int InialWork(Node *h) { Node *p,*w; p=(Node *)malloc(sizeof(Node)); p->data.size=4; strcpy(p->data.name,"p1"); p->data.a[0]=4; p->data.a[1]=5; p->data.a[2]=6; p->data.a[3]=31; w=(Node *)malloc(sizeof(Node)); w->data.size=6; strcpy(w->data.name,"p2"); w->data.a[0]=0; w->data.a[1]=1; w->data.a[2]=9; w->data.a[3]=11; w->data.a[4]=13; w->data.a[5]=24; p->next=w; w->next=NULL; h->next=p; return 0; } int AddWork(Node *h) { int g=0,i,j,w; Node *p; Node *q; q=h; while(h->next!=NULL) { h=h->next; } p=(Node *)malloc(sizeof(Node)); //分配空間 printf("請輸入進程的所需塊數"); scanf("%d",&p->data.size); if(p->data.size>kongxiankuai()) { printf("內存不足。\n"); return 0; } w=p->data.size; while(w!=0) { printf("請輸入作業名:\n"); scanf("%10s",p->data.name); while(q!=NULL) { if(strcmp(q->data.name,p->data.name)==0) { printf("該作業存在,重新輸入。\n\n"); return 0; } q=q->next; } for(i=0;i<8;i++) { for(j=0;j<8;j++) { if(table[i][j]==0&&w!=0)//作業分配存儲 { table[i][j]=1; p->data.a[g]=i*8+j; //保存作業塊號 g++; w=w-1; } } } } printf("作業添加成功\n\n"); h->next=p; p->next=NULL; return 0; } void PrintWork(Node *h)//打印頁表 { Node *p; int i; printf("打印作業表\n"); p=h->next; while(p!=NULL) { printf("作業名:"); printf("%s\n",p->data.name); for(i=0;i<p->data.size;i++) { printf("頁號:%-3d 塊號:%-3d\n",i,p->data.a[i]); } p=p->next; } printf("\n"); } void PrintPicture()//打印位示圖 { int i,j; printf("打印位示圖\n"); printf(" "); for(i=0;i<8;i++) { printf("%3d",i); } printf("\n"); for(i=0;i<8;i++) { printf("%3d",i); for(j=0;j<8;j++) { printf("%3d",table[i][j]); } printf("\n"); } printf("剩余空閑塊:%d",kongxiankuai()); printf("\n"); printf("\n"); } int EndingWork(Node *h) //按照需要釋放內存 { int i,m,n; Node *node1 = h; Node *node2 = NULL; char name[10]; printf("請輸入歸還的作業名:"); scanf("%10s",name); if(h->next== NULL) { printf("作業表為空\n\n"); return 0; } else {
while(node1->next!= NULL) { node2 = node1; node2 = node1 -> next; if(strcmp(node2->data.name,name)==0) { node1 -> next = node2 -> next; for(i=0;i<node2->data.size;i++) { printf("回收的塊號:%d\n",node2->data.a[i]); m = node2->data.a[i]/8; n = node2->data.a[i]%8; table[m][n]=0; } printf("\n"); free(node2); return 0; } node1 = node1 -> next; } printf("沒有該作業\n\n"); return 0; } } int main() { int q; Node *h; h=(Node *)malloc(sizeof(Node)); h->next=NULL; Initial(); InialWork(h); while(1) { menu(); printf("請輸入選擇:\n"); scanf("%d",&q); switch(q) { case 1: PrintPicture(); break; case 2: AddWork(h); break; case 3: EndingWork(h); break; case 4: PrintWork(h); break; case 5: exit(0); break; } } return 0; }