一、實習內容
主存儲器空間的分配和回收。

二、實習目的
通過本實習幫助理解在不同的存儲管理方式下應怎樣進行存儲空間的分配和回收。

三、實習題目
在分頁管理方式下採用位示圖來表示主存分配情況,實現主存分配和回收

四、設計思想
1.設計思路
(1)假定系統的主存被分成大小相等的64個塊,用0/1對應空閑/佔用。
(2)當要裝入一個作業時,根據作業對主存的需求量,先查空閑塊數是否能滿足作業要求,若能滿足,則查位示圖,修改位示圖和空閑塊數。位置與塊號的對應關係為:
塊號=j*8+i,其中i表示位,j表示字節。
根據分配的塊號建立頁表。頁表包括兩項:頁號和塊號。
(3)回收時,修改位示圖和空閑塊數。


2.主要數據結構

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct bitGraph
{
	int a[8][8];//位示圖
	int freebit;//空閑塊數
}BG;
 
//進程的數據結構
struct proc
{
	char name[10];//進程名
	int *PT;//頁表
	int size;//進程所需要的空間
	struct proc *next;
	struct proc *front;
};

3.主要代碼結構及代碼段分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//分配內存
int getMalloc()
{
	int i = 0,j = 0,p = 0,k = 0,flag = 0;
	struct proc *process;
	process = (struct proc *)malloc(sizeof(struct proc));
	printf("請輸入進程名:\n");
	scanf("%10s",process->name);
	process->next = head->next;
	if(head->next != NULL)
		head->next->front = process;
	head->next = process;
	process->front = head;
	printf("請輸入進程所需內存大小:\n");
	scanf("%d",&process->size);
	if(process->size > BG.freebit)
	{
		printf("對不起,空閑空間不足以分配如此多內存給該進程。\n");
		return 0;
	}
	else
	{
		process->PT = new int [process->size];
		for(i=0;i<8 && flag==0;i++)
			for(j=0;j<8 && flag==0;j++)
			{
				if(!BG.a[i][j])
				{
					BG.a[i][j] = 1;
					BG.freebit--;
					process->PT[k] = 8*i + j;
					k++;
					if(k == process->size)
						flag = 1;
				}
			}
	}
	printf("\n位示圖:\n");
	for(i=0;i<8;i++)
	{
		for(j=0;j<8;j++)
			printf("%d",BG.a[i][j]);
		printf("\n");
	}
}
 
//回收內存
int setFree()
{
	char name[10];
	int flag = 0,i = 0,j = 0;
	struct proc *p = head;
	printf("請輸入需要回收的進程名:");
	scanf("%10s",&name);
	for(p = head;p != NULL;p = p->next)
	{
		if(strcmp(p->name , name)==0)//找到該進程,將其從進程鏈表中刪除,並改寫位示圖
		{
			flag = 1;
			for(i=0;i < p->size;i++)
			{
				int m = p->PT[i]/8;
				int n = p->PT[i]%8;
				BG.a[m][n]= 0;
				BG.freebit++;
			}
			if(p->front != NULL)
			{
				if(p->next != NULL)
				{
					p->front->next = p->next;
					p->next->front = p->front;
					free(p);
				}
				else
				{
					p->front->next = p->next;
					free(p);
				}
			}
			else
			{
				p->next->front = p->front;
				free(p);
			}
		}
	}
	if(flag == 0)
		printf("沒有該進程!\n");
	else
		printf("回收成功!\n");
	printf("\n位示圖:\n");
	for(i=0;i<8;i++)
	{
		for(j=0;j<8;j++)
			printf("%d",BG.a[i][j]);
		printf("\n");
	}
}
 
//顯示進程頁表
int showMemo()
{
	char name[10];
	int flag = 0,i = 0;
	struct proc *p = head;
 
	printf("請輸入進程名:");
	scanf("%10s",&name);
	for(p = head;p != NULL;p = p->next)
	{
		if(strcmp(p->name , name)==0)
		{
			printf("	進程名  頁號    塊號\n");
			for(i=0;i<p->size;i++)
			{
				printf("%10s	%d	%d\n",p->name,i,p->PT[i]);
				flag = 1;
			}
		}
	}
	if(flag == 0)
		printf("沒有該進程!\n");
}
 
int main()
{
	char choose;
	BG.a[8][8] = 0;
	BG.freebit = 64;
 
	head = (struct proc *)malloc(sizeof(struct proc));
	if(head==NULL)
	{
		printf("error in allocating...\n");
	}
	else
		printf("successed\n");
	head->next = head->front = NULL;//建立進程的頭結點
        char buf[128];
	do
	{
	system("clear");
	printf("---------------------------\n");
	printf("1.新進程請求內存空間\n");
	printf("2.回收空間\n");
	printf("3.顯示進程頁表\n");
	printf("4.退出\n");
	printf("---------------------------\n");
		printf("請選擇:");
		scanf("%c",&choose);
		switch(choose)
		{
			case '1':
				getMalloc();
				gets(buf);break;
			case '2':
				setFree();
				gets(buf);break;
			case '3':
				showMemo();
				gets(buf);break;
			case '4':
				exit(1);gets(buf);break;
			default:
				gets(buf);
				printf("輸入錯誤!請重新輸入。\n");break;
		}
		printf("\n");
		getchar();
	}while(choose != '4');
}

五、上機實習所用平台及相關軟件
本程序在Linux平台(Ubuntu8.04.1)下,使用vi編輯器編寫,g++編譯通過。

六、調試過程
測試數據:
進程名    請求內存大小
aaa    3
bbb    10
ccc    30
ddd    1000
測試結果:
截圖(略)

七、總結
(1)我使用了一個二維數組作為位示圖的數據結構,這樣簡單明了。而進程頁表使用一個一維數組,用數組下標即可表示頁號,節省了存儲空間。
(2)在程序中充分考慮到出錯處理。比如在功能選擇菜單中,若用戶輸入非法字符則提示“輸入錯誤!請重新輸入”;在用戶申請內存時,若要求的空間大小大於空閑空間大小,則提示“空閑空間不足”;在回收內存空間和顯示進程頁表時,若用戶輸入的進程名不存在,則提示“沒有該進程”。這樣提高了程序的健壯性。
(3)通過本實驗,我進一步加深了對使用位示圖方式表示和實現主存分配回收的理解,同時也得到了將系統理論實踐的機會,熟練了編程能力。