操作系统实验(二)—— 使用动态分区分配方式的模拟

本文最后更新于:2019年12月21日 上午

概览首次适应算法最佳适应算法的动态分区分配。

实验内容

用C语言分别实现采用首次适应算法和最佳适应算法的动态分区分配过程alloc( )和回收过程free( )。其中,空闲分区通过空闲分区链来管理:在进行内存分配时,系统优先使用空闲区低端的空间。

假设初始状态下,可用的内存空间为640KB,并有下列的请求序列:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
•作业1申请130KB。

•作业2申请60KB。

•作业3申请100KB。

•作业2释放60KB。

•作业4申请200KB。

•作业3释放100KB。

•作业1释放130KB。

•作业5申请140KB。

•作业6申请60KB。

•作业7申请50KB。

•作业6释放60KB。

请分别采用首次适应算法和最佳适应算法,对内存块进行分配和回收,要求每次分配和回收后显示出空闲分区链的情况。

首次适应算法 FF

该算法从空闲分区链首开始查找,直至找到一个能满足其大小要求的空闲分区为止。然后再按照作业的大小,从该分区中划出一块内存分配给请求者,余下的空闲分区仍留在空闲分区链 中。

特点: 该算法倾向于使用内存中低地址部分的空闲区,在高地址部分的空闲区很少被利用,从而保留了高地址部分的大空闲区。显然为以后到达的大作业分配大的内存空间创造了条件。

缺点:低地址部分不断被划分,留下许多难以利用、很小的空闲区,而每次查找又都从低地址部分开始,会增加查找的开销。

最佳适应算法 BF

该算法总是把既能满足要求,又是最小的空闲分区分配给作业。为了加速查找,该算法要求将所有的空闲区按其大小排序后,以递增顺序形成一个空白链。这样每次找到的第一个满足要求的空闲区,必然是最优的。孤立地看,该算法似乎是最优的,但事实上并不一定。因为每次分配后剩余的空间一定是最小的,在存储器中将留下许多难以利用的小空闲区。同时每次分配后必须重新排序,这也带来了一定的开销。

特点:每次分配给文件的都是最合适该文件大小的分区。

缺点:内存中留下许多难以利用的小的空闲区。

代码思路

采用单链表来完成区间的分配释放的模拟。

需要申请一块空间就给单链表增加一个节点,然后修改原来节点的参数。

需要释放一块空间就找到单链表中对应的节点,改变其空间状态(占用 -> 空闲),然后查看该节点周边的节点状态,判断是否需要合并。

首次适应算法代码

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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#include <iostream>
#include <conio.h>

using namespace std;

struct Memory
{
int begin_add;
int end_add;
int size;
bool state;//false表示空闲
int pro_id;//申请内存的作业id
Memory *next;
};

void InitMemory(Memory* oneMemoryHead)
{
Memory* oneMemory = (Memory*)malloc(sizeof(Memory));
oneMemory->begin_add = 0;
oneMemory->end_add = 640;
oneMemory->size = 640;
oneMemory->state = false;
oneMemory->pro_id = -1; //当分区域空闲时 pro_id为-1
oneMemory->next = NULL;

oneMemoryHead->next = oneMemory;
}

//FF算法
void RequestMemoryByFF(Memory* oneMemoryHead,int RequestId,int RequestSize)
{
Memory * p_before = oneMemoryHead;
Memory *p = oneMemoryHead->next;
while (p!=NULL)
{
if (p->state == false && p->size >= RequestSize)
{
//申请内存
Memory * newMemory = (Memory*)malloc(sizeof(Memory));
newMemory->begin_add = p->begin_add;
newMemory->end_add = p->begin_add + RequestSize;
newMemory->size = RequestSize;
newMemory->pro_id = RequestId;
newMemory->state = true;
newMemory->next = p;

p_before->next = newMemory;

//修改剩余内存的
p->begin_add = p->begin_add + RequestSize;
p->size = p->size - RequestSize;

//如果剩余内存变成0
if (p->size == 0)
{
p_before->next = p->next;
}
//跳出循环
break;
}
else
{
p_before = p;
p = p->next;
}
}
}

void FreeMemory(Memory* oneMemoryHead, int FreeId, int FreeSize)
{
Memory * p_before = oneMemoryHead;
Memory *p = oneMemoryHead->next;
while (p != NULL)
{
if (p->pro_id == FreeId)
{
//释放内存
p->state = false;
p->pro_id = -1;
//寻找周围的内存,查看是否是空闲内存
if (p_before->state == false)
{
//前面的内存,合并
p_before->end_add += FreeSize;
p_before->size += FreeSize;
p_before->next = p->next;
p = p_before;
}

if (p->next!= NULL && p->next->state == false)
{
//后面的内存,合并
p->end_add += p->next->size;
p->size += p->next->size;
p->next = p->next->next;
}

//跳出循环
break;
}
else
{
p_before = p;
p = p->next;
}
}
}

void ShowMemory(Memory* oneMemoryHead)
{
Memory* p = oneMemoryHead->next;
while (p!=NULL)
{
cout << "\tBegin Address: " << p->begin_add << " End Address: " << p->end_add << " Size: " << p->size<<
" State: "<<p->state<<" Pro_Id:"<<p->pro_id<< endl;
p = p->next;
}
}

int main()
{
Memory *oneMemoryHead = (Memory *)malloc(sizeof(Memory));
oneMemoryHead->state = true;
oneMemoryHead->next = NULL;
InitMemory(oneMemoryHead);

cout << "FF" << endl;

cout << "作业1申请130KB" << endl;
RequestMemoryByFF(oneMemoryHead,1,130);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业2申请60KB。" << endl;
RequestMemoryByFF(oneMemoryHead,2,60);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业3申请100KB。" << endl;
RequestMemoryByFF(oneMemoryHead,3,100);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业2释放60KB。" << endl;
FreeMemory(oneMemoryHead,2,60);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业4申请200KB。" << endl;
RequestMemoryByFF(oneMemoryHead, 4, 200);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业3释放100KB。" << endl;
FreeMemory(oneMemoryHead, 3, 100);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业1释放130KB。" << endl;
FreeMemory(oneMemoryHead, 1, 130);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业5申请140KB。" << endl;
RequestMemoryByFF(oneMemoryHead, 5, 140);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业6申请60KB。" << endl;
RequestMemoryByFF(oneMemoryHead, 6, 60);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业7申请50KB。" << endl;
RequestMemoryByFF(oneMemoryHead, 7, 50);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业6释放60KB。" << endl;
FreeMemory(oneMemoryHead, 6, 60);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

_getch();
return 0;
}

结果

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
FF
作业1申请130KB
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 640 Size: 510 State: 0 Pro_Id:-1
==================
作业2申请60KB。
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 190 Size: 60 State: 1 Pro_Id:2
Begin Address: 190 End Address: 640 Size: 450 State: 0 Pro_Id:-1
==================
作业3申请100KB。
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 190 Size: 60 State: 1 Pro_Id:2
Begin Address: 190 End Address: 290 Size: 100 State: 1 Pro_Id:3
Begin Address: 290 End Address: 640 Size: 350 State: 0 Pro_Id:-1
==================
作业2释放60KB。
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 190 Size: 60 State: 0 Pro_Id:-1
Begin Address: 190 End Address: 290 Size: 100 State: 1 Pro_Id:3
Begin Address: 290 End Address: 640 Size: 350 State: 0 Pro_Id:-1
==================
作业4申请200KB。
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 190 Size: 60 State: 0 Pro_Id:-1
Begin Address: 190 End Address: 290 Size: 100 State: 1 Pro_Id:3
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 640 Size: 150 State: 0 Pro_Id:-1
==================
作业3释放100KB。
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 290 Size: 160 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 640 Size: 150 State: 0 Pro_Id:-1
==================
作业1释放130KB。
Begin Address: 0 End Address: 290 Size: 290 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 640 Size: 150 State: 0 Pro_Id:-1
==================
作业5申请140KB。
Begin Address: 0 End Address: 140 Size: 140 State: 1 Pro_Id:5
Begin Address: 140 End Address: 290 Size: 150 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 640 Size: 150 State: 0 Pro_Id:-1
==================
作业6申请60KB。
Begin Address: 0 End Address: 140 Size: 140 State: 1 Pro_Id:5
Begin Address: 140 End Address: 200 Size: 60 State: 1 Pro_Id:6
Begin Address: 200 End Address: 290 Size: 90 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 640 Size: 150 State: 0 Pro_Id:-1
==================
作业7申请50KB。
Begin Address: 0 End Address: 140 Size: 140 State: 1 Pro_Id:5
Begin Address: 140 End Address: 200 Size: 60 State: 1 Pro_Id:6
Begin Address: 200 End Address: 250 Size: 50 State: 1 Pro_Id:7
Begin Address: 250 End Address: 290 Size: 40 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 640 Size: 150 State: 0 Pro_Id:-1
==================
作业6释放60KB。
Begin Address: 0 End Address: 140 Size: 140 State: 1 Pro_Id:5
Begin Address: 140 End Address: 200 Size: 60 State: 0 Pro_Id:-1
Begin Address: 200 End Address: 250 Size: 50 State: 1 Pro_Id:7
Begin Address: 250 End Address: 290 Size: 40 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 640 Size: 150 State: 0 Pro_Id:-1
==================

最佳适应算法代码

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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include <iostream>
#include <conio.h>

using namespace std;

struct Memory
{
int begin_add;
int end_add;
int size;
bool state;//false表示空闲
int pro_id;//申请内存的作业id
Memory *next;
};

void InitMemory(Memory* oneMemoryHead)
{
Memory* oneMemory = (Memory*)malloc(sizeof(Memory));
oneMemory->begin_add = 0;
oneMemory->end_add = 640;
oneMemory->size = 640;
oneMemory->state = false;
oneMemory->pro_id = -1;
oneMemory->next = NULL;

oneMemoryHead->next = oneMemory;
}

void FreeMemory(Memory* oneMemoryHead, int FreeId, int FreeSize)
{
Memory * p_before = oneMemoryHead;
Memory *p = oneMemoryHead->next;
while (p != NULL)
{
if (p->pro_id == FreeId)
{
//释放内存
p->state = false;
p->pro_id = -1;
//寻找周围的内存,查看是否是空闲内存
if (p_before->state == false)
{
//前面的内存,合并
p_before->end_add += FreeSize;
p_before->size += FreeSize;
p_before->next = p->next;
p = p_before;
}

if (p->next != NULL && p->next->state == false)
{
//后面的内存,合并
p->end_add += p->next->size;
p->size += p->next->size;
p->next = p->next->next;
}

//跳出循环
break;
}
else
{
p_before = p;
p = p->next;
}
}
}

void ShowMemory(Memory* oneMemoryHead)
{
Memory* p = oneMemoryHead->next;
while (p != NULL)
{
cout << "\tBegin Address: " << p->begin_add << " End Address: " << p->end_add << " Size: " << p->size <<
" State: " << p->state << " Pro_Id:" << p->pro_id << endl;
p = p->next;
}
}

//找到合适的大小,适合当前申请的空间的 空闲分区中最小的那一块空间
Memory * FindJustyMemory(Memory* oneMemoryHead, int RequestSize)
{
Memory * p_before = oneMemoryHead;
Memory * p = oneMemoryHead->next;
Memory *tmp = NULL;
int tmpsize = 641;
while (p!=NULL)
{
if (p->state == false && p->size >= RequestSize)
{
if (tmpsize > p->size)
{
tmp = p;
tmpsize = p->size;
}
}
p_before = p;
p = p->next;
}
return tmp;
}

//BF算法
void RequestMemoryByBF(Memory* oneMemoryHead, int RequestId, int RequestSize)
{
Memory *p = FindJustyMemory(oneMemoryHead, RequestSize);
Memory * p_before = oneMemoryHead;
while (p_before->next != p)
{
p_before = p_before->next;
}
//维护 p_before永远时p的前一个

//申请内存
Memory * newMemory = (Memory*)malloc(sizeof(Memory));
newMemory->begin_add = p->begin_add;
newMemory->end_add = p->begin_add + RequestSize;
newMemory->size = RequestSize;
newMemory->pro_id = RequestId;
newMemory->state = true;
newMemory->next = p;

p_before->next = newMemory;

//修改剩余内存的
p->begin_add = p->begin_add + RequestSize;
p->size = p->size - RequestSize;

//如果剩余内存变成0
if (p->size == 0)
{
p_before->next = p->next;
}
}

int main()
{
Memory *oneMemoryHead = (Memory *)malloc(sizeof(Memory));
oneMemoryHead->state = true;
oneMemoryHead->next = NULL;
InitMemory(oneMemoryHead);

cout << "BF" << endl;

cout << "作业1申请130KB" << endl;
RequestMemoryByBF(oneMemoryHead, 1, 130);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业2申请60KB。" << endl;
RequestMemoryByBF(oneMemoryHead, 2, 60);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业3申请100KB。" << endl;
RequestMemoryByBF(oneMemoryHead, 3, 100);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业2释放60KB。" << endl;
FreeMemory(oneMemoryHead, 2, 60);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业4申请200KB。" << endl;
RequestMemoryByBF(oneMemoryHead, 4, 200);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业3释放100KB。" << endl;
FreeMemory(oneMemoryHead, 3, 100);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业1释放130KB。" << endl;
FreeMemory(oneMemoryHead, 1, 130);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业5申请140KB。" << endl;
RequestMemoryByBF(oneMemoryHead, 5, 140);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业6申请60KB。" << endl;
RequestMemoryByBF(oneMemoryHead, 6, 60);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业7申请50KB。" << endl;
RequestMemoryByBF(oneMemoryHead, 7, 50);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

cout << "作业6释放60KB。" << endl;
FreeMemory(oneMemoryHead, 6, 60);
ShowMemory(oneMemoryHead);
cout << "==================" << endl;

_getch();
return 0;
}

结果

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
BF
作业1申请130KB
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 640 Size: 510 State: 0 Pro_Id:-1
==================
作业2申请60KB。
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 190 Size: 60 State: 1 Pro_Id:2
Begin Address: 190 End Address: 640 Size: 450 State: 0 Pro_Id:-1
==================
作业3申请100KB。
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 190 Size: 60 State: 1 Pro_Id:2
Begin Address: 190 End Address: 290 Size: 100 State: 1 Pro_Id:3
Begin Address: 290 End Address: 640 Size: 350 State: 0 Pro_Id:-1
==================
作业2释放60KB。
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 190 Size: 60 State: 0 Pro_Id:-1
Begin Address: 190 End Address: 290 Size: 100 State: 1 Pro_Id:3
Begin Address: 290 End Address: 640 Size: 350 State: 0 Pro_Id:-1
==================
作业4申请200KB。
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 190 Size: 60 State: 0 Pro_Id:-1
Begin Address: 190 End Address: 290 Size: 100 State: 1 Pro_Id:3
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 640 Size: 150 State: 0 Pro_Id:-1
==================
作业3释放100KB。
Begin Address: 0 End Address: 130 Size: 130 State: 1 Pro_Id:1
Begin Address: 130 End Address: 290 Size: 160 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 640 Size: 150 State: 0 Pro_Id:-1
==================
作业1释放130KB。
Begin Address: 0 End Address: 290 Size: 290 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 640 Size: 150 State: 0 Pro_Id:-1
==================
作业5申请140KB。
Begin Address: 0 End Address: 290 Size: 290 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 630 Size: 140 State: 1 Pro_Id:5
Begin Address: 630 End Address: 640 Size: 10 State: 0 Pro_Id:-1
==================
作业6申请60KB。
Begin Address: 0 End Address: 60 Size: 60 State: 1 Pro_Id:6
Begin Address: 60 End Address: 290 Size: 230 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 630 Size: 140 State: 1 Pro_Id:5
Begin Address: 630 End Address: 640 Size: 10 State: 0 Pro_Id:-1
==================
作业7申请50KB。
Begin Address: 0 End Address: 60 Size: 60 State: 1 Pro_Id:6
Begin Address: 60 End Address: 110 Size: 50 State: 1 Pro_Id:7
Begin Address: 110 End Address: 290 Size: 180 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 630 Size: 140 State: 1 Pro_Id:5
Begin Address: 630 End Address: 640 Size: 10 State: 0 Pro_Id:-1
==================
作业6释放60KB。
Begin Address: 0 End Address: 60 Size: 60 State: 0 Pro_Id:-1
Begin Address: 60 End Address: 110 Size: 50 State: 1 Pro_Id:7
Begin Address: 110 End Address: 290 Size: 180 State: 0 Pro_Id:-1
Begin Address: 290 End Address: 490 Size: 200 State: 1 Pro_Id:4
Begin Address: 490 End Address: 630 Size: 140 State: 1 Pro_Id:5
Begin Address: 630 End Address: 640 Size: 10 State: 0 Pro_Id:-1
==================

不足

出于实验的考虑,没有增加任何的逻辑判断语句来判断内存不足或者其他情况