一、实验目的

通过本实验帮助学生理解在动态分区管理方式下应怎样实现主存空间的分配和回收。

二、实验内容

在动态分区管理方式下采用不同的分配算法实现主存分配和实现主存回收。

三、实验要求

(1)可变分区方式是按作业需要的主存空间大小来分割分区的。当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入。随着作业的装入、撤离、主存空间被分成许多个分区,有的分区被作业占用,而有的分区是空闲的。例如:

为了说明哪些区是空闲的,可以用来装入新作业,必须要有一张空区说明表,格式如下:

其中
起址——指出一个空闲区的主存起始地址。
长度——指出从起始地址开始的一个连续空闲区的长度。
状态——有两种状态,一种是“未分配”状态,指出对应的由起址指出的某个长度的区域是空闲区;另一种是“空表目”状态,表示表中对应的登记项目是空白(无效),可用来登记新的空闲区(例如,作业撤离后,它所占的区域就成了空闲区,应找一个“空表目”栏登记归还区的起址和长度且修改状态)。
由于分区的个数不定,所以空闲区说明表中应有适量的状态为“空表目”的登记栏目,否则造成表格“溢出”无法登记。

上述的这张说明表的登记情况是按提示

(1)中的例所装入的三个作业占用的主存区域后填写的

(2)当有一个新作业要求装入主存时,必须查空闲区说明表,从中找出一个足够大的空闲区。有时找到的空闲区可能大于作业需要量,这时应把原来的空闲区变成两部分:一个部分分给作业占用;另一部分又成为一个较小的空闲区。为了尽量减少由于分割造成的“碎片”,在作业请求装入时,尽可能地利用主存的低地址部分的空闲区,而尽量保存高地址部分有较大的连续空闲区域,以利于大型作业的装入。为此,在空闲区说明表中,把每个空闲区按其地址顺序登记,即每个后继的空闲区其起始地址总是比前者大。为了方便查找还可使表格“紧缩”,总是让“空表目”栏集中在表格的后部。

(3)采用首次适应算法或循环首次算法或最佳适应算法分配主存空间。由于本实验是模拟主存的分配,所以当把主存区分配给作业后并不实际启动装入程序装入作业,而用输出“分配情况”来代替。(即输出当时的空闲区说明表及其内存分配表)

(4)当一个作业执行结束撤离时,作业所占的区域应该归还,归还的区域如果与其它空闲区相邻,则应合成一个较大的空闲区,登记在空闲区说明表中。例如,在提示(1)中列举的情况下,如果作业2撤离,归还所占主存区域时,应与上、下相邻的空闲区一起合成一个大的空闲区登记在空闲区说明表中。

(5)请分别按首次适应算法、循环首次算法和最佳适应算法设计主存分配和回收的程序。然后按(1)中假设主存中已装入三个作业,且形成两个空闲区,确定空闲说明表的初值。现有一个需要主存量为6K的作业4 申请装入主存;然后作业3 撤离;再作业2 撤离。请你为它们进行主存分配和回收,把空闲区说明表的初值以及每次分配或回收后的变化显示出来或打印出来。

四、代码实现

MemoryAllocation.cpp

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

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

#include <iostream>

#include <Windows.h>

#include <fstream>

#include <string>

#include <queue>

using namespace std;

int MemorySize = 0;

int OSSize = 0;

int Memory[1000] = { 0 };

struct Struct1{

    int begin;

    int length;

    string state;//值为未分配或者空条目

};

queue<Struct1> WORK;//作业集合

queue<Struct1> EMPTY;//空区集合

//更新EMPTY队列,空区集合

void UpdateEMP(){

    while (!EMPTY.empty()) {

        EMPTY.pop();

    }

    for (int i = 0; i < MemorySize; i++) {

        if (Memory[i] == 0) {

            for (int j = i + 1; j < MemorySize; j++) {

                if (Memory[j] == 1 || j == MemorySize - 1) {

                    Struct1 emp1;

                    emp1.begin = i;

                    if (j == MemorySize - 1) {

                        emp1.length = j - i + 1;

                    }

                    else {

                        emp1.length = j - i;

                    }

                    emp1.state = "未分配";

                    EMPTY.push(emp1);

                    i = j;

                    break;

                }

            }

        }

    }

    cout << "现有的空区说明表为:" << endl;

    int s = EMPTY.size();

    cout << s << "块空区" << endl;

    for (int i = 0; i < s; i++) {

        Struct1 emp1;

        emp1 = EMPTY.front();

        EMPTY.push(emp1);

        EMPTY.pop();

        cout  << " 起始:" << emp1.begin << " 长度:" << emp1.length << " 状态:" << emp1.state << endl;

    }

}

//首次适应算法(FF)

void FF(int applyNum) {

    if (EMPTY.empty()) {

        cout << "没有足够的主存空间!!" << endl;

        exit(0);

    }

    bool flag = false;

    while (!EMPTY.empty()) {

        Struct1 emp1 = EMPTY.front();

        if (emp1.length > applyNum) {

            for (int i = emp1.begin; i< applyNum + emp1.begin ;i++) {

                Memory[i] = 1;

            }

            Struct1 work3;

            work3.begin = emp1.begin;

            work3.length = applyNum;

            work3.state = "作业4";

            WORK.push(work3);

            UpdateEMP();

            flag = true;

            break;

        }

        EMPTY.pop();

    }

    if (!flag) {

        cout << "没有足够的主存空间!!" << endl;

        exit(0);

    }

    Sleep(2000);

    //作业三撤离

    for (int i = 0; i < WORK.size(); i++) {

        Struct1 work1;

        work1 = WORK.front();

        if (work1.state == "作业3") {

            for (int i = work1.begin; i < work1.begin+ work1.length;i++) {

                Memory[i] = 0;

            }

            WORK.pop();

            cout << endl << "作业三撤离!" << endl;

            UpdateEMP();

            break;

        }

        else {

            WORK.pop();

            WORK.push(work1);

        }

    }

    Sleep(2000);

    //作业二撤离

    for (int i = 0; i < WORK.size(); i++) {

        Struct1 work1;

        work1 = WORK.front();

        if (work1.state == "作业2") {

            for (int i = work1.begin; i < work1.begin + work1.length; i++) {

                Memory[i] = 0;

            }

            WORK.pop();

            cout << endl << "作业二撤离!" << endl;

            UpdateEMP();

            break;

        }

        else {

            WORK.pop();

            WORK.push(work1);

        }

    }

}

//循环首次适应算法(NF)

void NF(int applyNum) {

    if (EMPTY.empty()) {

        cout << "没有足够的主存空间!!" << endl;

        exit(0);

    }

    bool flag = false;

    while (!EMPTY.empty()) {

        Struct1 emp1 = EMPTY.front();

        if (emp1.length > applyNum) {

            for (int i = emp1.begin; i < applyNum + emp1.begin; i++) {

                Memory[i] = 1;

            }

            Struct1 work3;

            work3.begin = emp1.begin;

            work3.length = applyNum;

            work3.state = "作业4";

            WORK.push(work3);

            UpdateEMP();

            flag = true;

            break;

        }

        EMPTY.pop();

    }

    if (!flag) {

        cout << "没有足够的主存空间!!" << endl;

        exit(0);

    }

    Sleep(2000);

    //作业三撤离

    for (int i = 0; i < WORK.size(); i++) {

        Struct1 work1;

        work1 = WORK.front();

        if (work1.state == "作业3") {

            for (int i = work1.begin; i < work1.begin + work1.length; i++) {

                Memory[i] = 0;

            }

            WORK.pop();

            cout << endl << "作业三撤离!" << endl;

            UpdateEMP();

            break;

        }

        else {

            WORK.pop();

            WORK.push(work1);

        }

    }

    Sleep(2000);

    //作业二撤离

    for (int i = 0; i < WORK.size(); i++) {

        Struct1 work1;

        work1 = WORK.front();

        if (work1.state == "作业2") {

            for (int i = work1.begin; i < work1.begin + work1.length; i++) {

                Memory[i] = 0;

            }

            WORK.pop();

            cout << endl << "作业二撤离!" << endl;

            UpdateEMP();

            break;

        }

        else {

            WORK.pop();

            WORK.push(work1);

        }

    }

}

//最佳适应算法(BF)

void BF(int applyNum) {

    if (EMPTY.empty()) {

        cout << "没有足够的主存空间!!" << endl;

        exit(0);

    }

    bool flag = false;

    int col = 10000000;//记录每一个空区与请求大小的差值

    string e = "";

    int em = EMPTY.size()*2;

    for (int i = 0; i < em; i++) {

        Struct1 emp1 = EMPTY.front();

        if (emp1.length > applyNum) {

            if (col == (emp1.length - applyNum) && e==emp1.state) {

                for (int i = emp1.begin; i < applyNum + emp1.begin; i++) {

                    Memory[i] = 1;

                }

                Struct1 work3;

                work3.begin = emp1.begin;

                work3.length = applyNum;

                work3.state = "作业4";

                WORK.push(work3);

                UpdateEMP();

                flag = true;

                break;

            }

            if (col > (emp1.length - applyNum)) {

                col = (emp1.length - applyNum);

                e = emp1.state;

            }

        }

        EMPTY.pop();

        EMPTY.push(emp1);

    }

    if (!flag) {

        cout << "没有足够的主存空间!!" << endl;

        exit(0);

    }

    Sleep(2000);

    //作业三撤离

    for (int i = 0; i < WORK.size(); i++) {

        Struct1 work1;

        work1 = WORK.front();

        if (work1.state == "作业3") {

            for (int i = work1.begin; i < work1.begin + work1.length; i++) {

                Memory[i] = 0;

            }

            WORK.pop();

            cout << endl << "作业三撤离!" << endl;

            UpdateEMP();

            break;

        }

        else {

            WORK.pop();

            WORK.push(work1);

        }

    }

    Sleep(2000);

    //作业二撤离

    for (int i = 0; i < WORK.size(); i++) {

        Struct1 work1;

        work1 = WORK.front();

        if (work1.state == "作业2") {

            for (int i = work1.begin; i < work1.begin + work1.length; i++) {

                Memory[i] = 0;

            }

            WORK.pop();

            cout << endl << "作业二撤离!" << endl;

            UpdateEMP();

            break;

        }

        else {

            WORK.pop();

            WORK.push(work1);

        }

    }

}

//主函数

int main() {

    //打印提示信息

    cout << "************************************************\n";

    cout << "        操作系统实验内存分配算法\n";

    cout << "        作者:CSDN Carmelo_7 主页: https://blog.csdn.net/Carmelo_7?spm=1000.2115.3001.5343 \n";

    cout << "************************************************\n";

    ifstream inFile;

    inFile.open("MemoryAllocation.dat");

    if (!inFile.is_open())

        cout << "文件打开时候出错!!" << endl;

    inFile >> MemorySize >> OSSize;

    cout << "请输入主存的现有状态" << endl;

    cout << "正在读取数据文件..." << endl;

    Sleep(2000);

    //打印空闲区说明表的初始状态

    cout << "主存总大小:" << MemorySize << endl <<"操作系统占用空间:" << OSSize <<endl;

    for (int i = 0;i<OSSize; i++) {

        Memory[i] = 1;

    }

    int n = 0;

    while (!inFile.eof()) {

        n++;

        Struct1 work1;

        inFile >> work1.begin >> work1.length;

        work1.state = "作业"+to_string(n);

        WORK.push(work1);

    }

    int s = WORK.size();

    for (int i = 0; i < s; i++) {

        Struct1 work2;

        work2 = WORK.front();

        WORK.push(work2);

        WORK.pop();

        cout << work2.state << " 起始:" << work2.begin << " 长度:" << work2.length << endl;

        for (int i = work2.begin; i < work2.length + work2.begin; i++) {

            Memory[i] = 1;

        }

    }

    /*for (int i : Memory) {

        cout << i;

    }*/

    UpdateEMP();

    cout << "请输入新的作业的申请主存数量:" << endl;

    //打印作业4的申请量

    int applyNum = 0;

    cin >> applyNum;

    cout << "作业" << n << "申请了"<< applyNum <<"主存空间" << endl;

    cout << "===================================================================================" << endl;

    cout << "1.首次适应算法(FF) :将所有空闲分区按照地址递增的次序链接,在申请内存分配时,从链首开始查找,将满足需求的第一个空闲分区分配给作业。" << endl;

    cout << "2.循环首次适应算法(NF):将所有空闲分区按照地址递增的次序链接,在申请内存分配时,总是从上次找到的空闲分区的下一个空闲分区开始查找,将满足需求的第一个空闲分区分配给作业" << endl;

    cout << "3.最佳适应算法(BF) : 将所有空闲分区按照从小到大的顺序形成空闲分区链,在申请内存分配时,总是把满足需求的、最小的空闲分区分配给作业。" << endl;

    cout << "===================================================================================" << endl;

    cout << "请输入对应的序号选择算法:" << endl;

    int choose = 0;

    cin >> choose;

    switch (choose) {

        case 1:

            FF(applyNum);

            break;

        case 2:

            NF(applyNum);

            break;

        case 3:

            BF(applyNum);

            break;

        default:

            cout << "你输入的序号有误!!!" << endl;

            exit(0);

            break;

    }

}

MemoryAllocation.dat

1

2

3

4

128 5

5 5

26 6

10 4

五、测试样例

到此这篇关于C++ 操作系统内存分配算法的实现详解的文章就介绍到这了

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐