操作系统 动态分区存储管理(循环首次适应算法、最坏适应算法)

操作系统 动态分区存储管理

实验要求
通过编写动态分区存储管理的模拟程序,加深对操作系统存储管理功能中的动态分区管理方式、空闲分区表等相应知识的理解。

实验内容
实现动态分区存储管理方式下存储空间的分配和去配。

  1. 循环首次适应算法:每次都从上一次分配的空闲区继续循环遍历所有的空闲区。若再次回到上一次的位置,就代表没有可用的空闲区。

  2. 最坏适应算法:每次都寻找最大的空闲区进行分配,如果最大的空闲区都不够分配那么就没有可分配的空闲区。

当进程移出空闲区后需要进行空闲区的合并。将相邻的空闲区合并成一个分区。

作业流程
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
----------------------------------------
*****************************
请按任意键继续. . .

你可能感兴趣的:(操作系统,c++,算法,操作系统,数据结构)