实验要求
通过编写动态分区存储管理的模拟程序,加深对操作系统存储管理功能中的动态分区管理方式、空闲分区表等相应知识的理解。
实验内容
实现动态分区存储管理方式下存储空间的分配和去配。
循环首次适应算法:每次都从上一次分配的空闲区继续循环遍历所有的空闲区。若再次回到上一次的位置,就代表没有可用的空闲区。
最坏适应算法:每次都寻找最大的空闲区进行分配,如果最大的空闲区都不够分配那么就没有可分配的空闲区。
当进程移出空闲区后需要进行空闲区的合并。将相邻的空闲区合并成一个分区。
作业流程
j0~j6调入,j2、j3调出,j5调入,j0、j1调出,j0调入,j5调出,j6调入,j0、j4、j6调出
//Partition.h
#pragma once
#include
using namespace std;
///
/// 空闲分区类
///
class Partition
{
public:
double startAddress;//分区开始地址
double length;//分区长度
Partition(double startAddress, double length);
};
///
/// 作业
///
class Job
{
public:
int num;//作业编号
bool enter;//是否已经调入内存
double startAddress;//内存中的起始地址
double size;//大小
Job(double size, int num);
};
///
/// 作业流程
///
class JobFlow
{
public:
Job* job;//作业
bool enter;//标志作业是要调入内存还是调出内存
JobFlow(Job* job, bool enter);
};
//Partition.cpp
#include "Partition.h"
///
/// 构造函数
///
/// 空闲分区起始地址
/// 长度
Partition::Partition(double startAddress, double length)
{
this->startAddress = startAddress;
this->length = length;
}
///
/// 构造函数
///
/// 作业大小
/// 作业编号
Job::Job(double size, int num)
{
this->num = num;
this->enter = false;
this->startAddress = -1;
this->size = size;
}
///
/// 构造函数
///
/// 作业
/// 该作业是要调入内存还是调出内存
JobFlow::JobFlow(Job* job, bool enter)
{
this->job = job;
this->enter = enter;
}
//DynamicPartitionStorageManagement.h
#pragma once
#include
#include
#include "Partition.h"
using namespace std;
///
/// 动态分区存储管理
///
class DynamicPartitionStorageManagement
{
static double threshold;//阈值
static void mergePartition(list<Partition>& P, list<Partition>::iterator curitr);
static void mergeFront(list<Partition>& P, list<Partition>::iterator curitr);
static void mergeBack(list<Partition>& P, list<Partition>::iterator curitr);
public:
static void printTable(list<Partition>& P);
static void nextFit(list<Partition>& P, list<JobFlow>& J);
static void worstFit(list<Partition>& P, list<JobFlow>& J);
};
//DynamicPartitionStorageManagement.cpp
#include "DynamicPartitionStorageManagement.h"
double DynamicPartitionStorageManagement::threshold = 0.1;
///
/// 打印空闲分区表
///
/// 空闲分区链表
void DynamicPartitionStorageManagement::printTable(list<Partition>& P)
{
int num = 0;
cout << "----------------------------------------" << endl;
cout << "分区编号" << "\t起始地址" << "\t空间大小" << endl;
for (list<Partition>::iterator itr = P.begin(); itr != P.end(); itr++)
{
cout << num++ << "\t\t" << itr->startAddress << "\t\t" << itr->length << endl;
}
cout << "----------------------------------------" << endl;
}
///
/// 合并前一分区
///
/// 空闲分区链表
/// 当前分区
void DynamicPartitionStorageManagement::mergeFront(list<Partition>& P, list<Partition>::iterator curitr)
{
list<Partition>::iterator preitr = curitr;
preitr--;
if (curitr->startAddress - preitr->startAddress - preitr->length
< DynamicPartitionStorageManagement::threshold)//与前一块分区合并
{
curitr->length = curitr->length + curitr->startAddress - preitr->startAddress;
curitr->startAddress = preitr->startAddress;
P.erase(preitr);
}
}
///
/// 合并后一分区
///
/// 空闲分区链表
/// 当前分区
void DynamicPartitionStorageManagement::mergeBack(list<Partition>& P, list<Partition>::iterator curitr)
{
list<Partition>::iterator nextitr = curitr;
nextitr++;
if (nextitr->startAddress - curitr->startAddress - curitr->length
< DynamicPartitionStorageManagement::threshold)//与后一块分区合并
{
curitr->length = nextitr->length + nextitr->startAddress - curitr->startAddress;
P.erase(nextitr);
}
}
///
/// 合并分区
///
/// 空闲分区链表
/// 当前分区
void DynamicPartitionStorageManagement::mergePartition(list<Partition>& P, list<Partition>::iterator curitr)
{
list<Partition>::iterator lastitr = P.end();//标志最后一块分区
lastitr--;
if (curitr != P.begin() && curitr != lastitr)//当前空闲区不在首尾
{
DynamicPartitionStorageManagement::mergeFront(P, curitr);
DynamicPartitionStorageManagement::mergeBack(P, curitr);
}
else if (curitr == P.begin() && curitr != lastitr)//当前空闲区在开头且不在末尾
{
DynamicPartitionStorageManagement::mergeBack(P, curitr);
}
else if (curitr != P.begin() && curitr == lastitr)//当前空闲区在末尾且不在开头
{
DynamicPartitionStorageManagement::mergeFront(P, curitr);
}
//既在开头又在结尾说明只有一块空闲分区,此时不需要合并
}
///
/// 循环首次适应算法
///
/// 空闲分区链表
/// 作业流程链表
void DynamicPartitionStorageManagement::nextFit(list<Partition>& P, list<JobFlow>& J)
{
list<Partition>::iterator lastitr = P.begin();//存放上次迭代器的位置
for (list<JobFlow>::iterator jitr = J.begin(); jitr != J.end(); jitr++)//遍历作业流程
{
bool enough = false;//标志足够分配
list<Partition>::iterator pitr = P.begin();
if (jitr->enter == true)//作业需要加入内存
{
enough = false;
pitr = lastitr;
do
{
if (pitr->length >= jitr->job->size)//足够分配
{
cout << "J" << jitr->job->num << "内存分配成功" << endl;
enough = true;
jitr->job->enter = true;
jitr->job->startAddress = pitr->startAddress;
pitr->startAddress += jitr->job->size;
pitr->length -= jitr->job->size;
if (pitr->length < DynamicPartitionStorageManagement::threshold)//由于浮点数精度问题,此时就认为空闲区大小与作业大小相等
{
P.erase(pitr);//删除当前空闲区
}
if (pitr == P.end())//若pitr为最后一个元素,erase之后会指向end,需要提前修改
{
pitr = P.begin();
}
lastitr = pitr;
break;
}
pitr++;
if (pitr == P.end())//若pitr为end而lastitr为begin是不加会死循环
{
pitr = P.begin();
}
} while (pitr != lastitr);
if (enough == false)//内存不足分配
{
cout << "内存不足,J" << jitr->job->num << "分配失败" << endl;
}
DynamicPartitionStorageManagement::printTable(P);
}
else//作业调出内存
{
if (jitr->job->enter == true)//作业已经调入内存
{
jitr->job->enter = false;
cout << "J" << jitr->job->num << "调出成功" << endl;
for (pitr = P.begin(); pitr != P.end(); pitr++)//按地址顺序插入一块新的空闲区
{
if (pitr->startAddress > jitr->job->startAddress)
{
break;
}
}
pitr = P.insert(pitr, Partition(jitr->job->startAddress, jitr->job->size));
DynamicPartitionStorageManagement::mergePartition(P, pitr);
lastitr = pitr;//合并之后可能会删除lastitr指向的节点,需要重新设置一个lastitr
DynamicPartitionStorageManagement::printTable(P);
}
}
}
}
///
/// 最坏适应算法
///
/// 空闲分区链表
/// 作业流程链表
void DynamicPartitionStorageManagement::worstFit(list<Partition>& P, list<JobFlow>& J)
{
for (list<JobFlow>::iterator jitr = J.begin(); jitr != J.end(); jitr++)//遍历作业流程
{
bool enough = false;//标志足够分配
list<Partition>::iterator maxitr = P.begin();
if (jitr->enter == true)//作业需要加入内存
{
enough = false;
for (list<Partition>::iterator pitr = P.begin(); pitr != P.end(); pitr++)//寻找最大空闲区
{
if (pitr->length >= jitr->job->size)//足够分配
{
enough = true;
if (maxitr->length < pitr->length)
{
maxitr = pitr;
}
}
}
if (enough == true)//找到空闲区
{
cout << "J" << jitr->job->num << "内存分配成功" << endl;
jitr->job->enter = true;
jitr->job->startAddress = maxitr->startAddress;
maxitr->startAddress += jitr->job->size;
maxitr->length -= jitr->job->size;
if (maxitr->length < DynamicPartitionStorageManagement::threshold)//由于浮点数精度问题,此时就认为空闲区大小与作业大小相等
{
P.erase(maxitr);//删除当前空闲区
}
}
else//未找到空闲区
{
cout << "内存不足,J" << jitr->job->num << "分配失败" << endl;
}
DynamicPartitionStorageManagement::printTable(P);
}
else//作业调出内存
{
if (jitr->job->enter == true)//作业已经调入内存
{
list<Partition>::iterator pitr;
jitr->job->enter = false;
cout << "J" << jitr->job->num << "调出成功" << endl;
for (pitr = P.begin(); pitr != P.end(); pitr++)//按地址顺序插入一块新的空闲区
{
if (pitr->startAddress > jitr->job->startAddress)
{
break;
}
}
pitr = P.insert(pitr, Partition(jitr->job->startAddress, jitr->job->size));
DynamicPartitionStorageManagement::mergePartition(P, pitr);
DynamicPartitionStorageManagement::printTable(P);
}
}
}
}
Partition p(0, 200);
list<Partition> P;
P.push_back(p);
Job j0(20, 0), j1(25.5, 1), j2(50, 2), j3(33.4, 3), j4(41.3, 4), j5(55, 5), j6(66.6, 6);
//j0~j6调入,j2、j3调出,j5调入,j0、j1调出,j0调入,j5调出,j6调入,j0、j4、j6调出
JobFlow jf0(&j0, true), jf1(&j1, true), jf2(&j2, true), jf3(&j3, true), jf4(&j4, true),
jf5(&j5, true), jf6(&j6, true), jf7(&j2, false), jf8(&j3, false), jf9(&j5, true),
jf10(&j0, false), jf11(&j1, false), jf12(&j0, true), jf13(&j5, false), jf14(&j6, true),
jf15(&j0, false), jf16(&j4, false), jf17(&j6, false);
list<JobFlow> J;
J.push_back(jf0);
J.push_back(jf1);
J.push_back(jf2);
J.push_back(jf3);
J.push_back(jf4);
J.push_back(jf5);
J.push_back(jf6);
J.push_back(jf7);
J.push_back(jf8);
J.push_back(jf9);
J.push_back(jf10);
J.push_back(jf11);
J.push_back(jf12);
J.push_back(jf13);
J.push_back(jf14);
J.push_back(jf15);
J.push_back(jf16);
J.push_back(jf17);
cout << "**********Next Fit**********" << endl;
DynamicPartitionStorageManagement::nextFit(P, J);
cout << "****************************" << endl;
cout << "**********Worst Fit**********" << endl;
DynamicPartitionStorageManagement::worstFit(P, J);
cout << "*****************************" << endl;
结果
**********Next Fit**********
J0内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 20 180
----------------------------------------
J1内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 45.5 154.5
----------------------------------------
J2内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 95.5 104.5
----------------------------------------
J3内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 128.9 71.1
----------------------------------------
J4内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 170.2 29.8
----------------------------------------
内存不足,J5分配失败
----------------------------------------
分区编号 起始地址 空间大小
0 170.2 29.8
----------------------------------------
内存不足,J6分配失败
----------------------------------------
分区编号 起始地址 空间大小
0 170.2 29.8
----------------------------------------
J2调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 45.5 50
1 170.2 29.8
----------------------------------------
J3调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 45.5 83.4
1 170.2 29.8
----------------------------------------
J5内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 100.5 28.4
1 170.2 29.8
----------------------------------------
J0调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 0 20
1 100.5 28.4
2 170.2 29.8
----------------------------------------
J1调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 0 45.5
1 100.5 28.4
2 170.2 29.8
----------------------------------------
J0内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 20 25.5
1 100.5 28.4
2 170.2 29.8
----------------------------------------
J5调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 20 108.9
1 170.2 29.8
----------------------------------------
J6内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 86.6 42.3
1 170.2 29.8
----------------------------------------
J0调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 0 20
1 86.6 42.3
2 170.2 29.8
----------------------------------------
J4调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 0 20
1 86.6 113.4
----------------------------------------
J6调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 0 200
----------------------------------------
****************************
**********Worst Fit**********
J0内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 20 180
----------------------------------------
J1内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 45.5 154.5
----------------------------------------
J2内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 95.5 104.5
----------------------------------------
J3内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 128.9 71.1
----------------------------------------
J4内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 170.2 29.8
----------------------------------------
内存不足,J5分配失败
----------------------------------------
分区编号 起始地址 空间大小
0 170.2 29.8
----------------------------------------
内存不足,J6分配失败
----------------------------------------
分区编号 起始地址 空间大小
0 170.2 29.8
----------------------------------------
J2调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 45.5 50
1 170.2 29.8
----------------------------------------
J3调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 45.5 83.4
1 170.2 29.8
----------------------------------------
J5内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 100.5 28.4
1 170.2 29.8
----------------------------------------
J0调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 0 20
1 100.5 28.4
2 170.2 29.8
----------------------------------------
J1调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 0 45.5
1 100.5 28.4
2 170.2 29.8
----------------------------------------
J0内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 20 25.5
1 100.5 28.4
2 170.2 29.8
----------------------------------------
J5调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 20 108.9
1 170.2 29.8
----------------------------------------
J6内存分配成功
----------------------------------------
分区编号 起始地址 空间大小
0 86.6 42.3
1 170.2 29.8
----------------------------------------
J0调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 0 20
1 86.6 42.3
2 170.2 29.8
----------------------------------------
J4调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 0 20
1 86.6 113.4
----------------------------------------
J6调出成功
----------------------------------------
分区编号 起始地址 空间大小
0 0 200
----------------------------------------
*****************************
请按任意键继续. . .