操作系统-动态分区式存贮区管理

报告下载:地址。。(绝对原创,请勿抄袭)

(一)、程序功能:模拟动态分区式存贮区管理

(二)、设计思路:

1、设计一个动态分区式存贮区管理程序,支持不同的放置策略。如首次、最佳、最坏。

2、分区描述器中为 :flag/size/next;

3、自由主存队列按链表组织,主存大小假设为maxsize(单位为节=rd的大小)。

4、作业申请n节,实际分配的分区大小应为n+1节。 其中一节作为分区描述器,其他n节提供给作业。

5、已分配区放在高地址处。

6、合并时应考虑四种情况:

假设回收区为r,上邻为f1(f1需搜索自由主存队列),下邻为f2(f2可直接计算)

A) f1空闲,f2已分配;

B) f1已分配,f2空闲;

C) f1空闲,f2空闲;

D) f1已分配,f2已分配;

(三)、数据结构

1、PCB类(进程控制器):

私有数据成员

类型

名称

注释

int

begin

进程开始的首地址

int

size

进程占用的大小

string

name

进程名

函数

声明

注释

PCB(string n="无'",int s=0,int b=0)

构造函数

ostream& operator<<(ostream&os, PCB&P)

重定义输出函数

注:PCB类是manage类的友元类。

2、block类(分区描述器):

私有数据成员

类型

名称

注释

int

m_size

分区的大小

bool

m_falg

判断该分区是否被占用

block*

next

下一个分区的地址

函数

函数声明

注释

block(bool flag = false… …)

构造函数

ostream& operator<<(ostream&os, block&P)

重定义输出函数

注:block类是manage类的友元类。

3、manage类

私有数据成员

类型

名称

注释

block*

first;

分区链表首地址

vector<PCB>

lib;

未结束的所有进程

函数 

声明

注释

manage()

构造函数

void first_time();

首次适应算法

void best();

最佳适应算法

void worst();

最坏适应算法

void free();

内存回收

void show();

显示内存分配情况

 

(四)、算法设计

1、首次适应算法

首次适应算法是将程序放入到主存中,按地址查找到第一个能装入它的空闲区。在首次适应算法中,空闲区是按其位置的顺序链接在一起,即每一个后继空闲去的起始地址总比他前者大。当要分配一个分区时,总是从低地址空闲区开始查寻,直到找到第一个足以满足该程序要求的空闲区为止。

代码:

 

void manage::first_time() {

	cout << "输入进程名和大小:";
	string name; int size,addr(0);
	cin >> name >> size;
	block* p(first);

	while (p != nullptr) {						//寻找块
		addr +=(p->m_size+1);					//计算地址
		if (p->m_flag == false) {				//当前块未被占用
			if (p->m_size > size) {			//当前块的大小大于进程申请的大小
				p->m_size -= (size + 1);		//从当前块中减去进程申请的大小
				block* temp=new block(true,size,p->m_next);	//新建一个进程块
				p->m_next = temp;				//添加到当前块的后面
				addr -= (size + 1);			//重新计算当前块的地址
				break;
			}
			else if (p->m_size == size) {	//当前块的大小刚好够进程申请的大小
				p->m_flag = true;			//直接更改当前块的状态为已占用,不用分裂块
				addr -= (size + 1);		//重新计算地址
				break;
			}
			else p = p->m_next;		//当前块的大小不满足进程申请的大小,先后继续寻找。
		}
		else p = p->m_next;				//当前块已被占用,先后继续寻找
	}
	if (p == nullptr)cout << "分配失败" << endl;	//未找到符合条件的块,分配失败
	else {								//找到符合条件的块,该进程存入lib进程库中
		PCB temp(name, size, addr);
		lib.push_back(temp);
	}
}

 

 

 

 

 

2、最佳适应算法

最佳适应算法是将程序放入主存中与他所需大小最接近的空闲区中,在最佳适应算法中,空闲区队列是按空闲区大小递增顺序链接在一起的。在进行分配时总是从最小的空闲区开始查寻,因而找到的第一个能满足要求的空闲区便是最佳的一个。即从所要求的大小来看,该区和气候的所有空闲区相比它是最接近的。
代码:

 

void manage::best() {

	cout << "输入进程名和大小:";
	string name; int size, addr1(0),addr2(0);
	cin >> name >> size;
	block *p(first),*q(nullptr);
	int Error(512);

	while (p != nullptr) {
		addr1 += (p->m_size + 1);
		if (p->m_flag == false) {		//当前块未被占用
			if (p->m_size > size) {	//当前块的大小满足进程请求的大小
				if (p->m_size - size < Error) {	//当前块更合适该进程
					Error = p->m_size - size;	//计算偏差
					q = p;			//保存当前块的地址
					addr2 = addr1 - size - 1;
					p = p->m_next;	//指针后移
				}
				else p = p->m_next;	//和之前的块相比,之前的块更合适该进程
			}
			else if (p->m_size == size) {	//当前块的大小刚好等于进程申请的大小
				q = p;				//已找到最合适的块,保存当前块的信息并退出
				addr2 = addr1 - size - 1;
				Error = 0;
				break;
			}
			else p = p->m_next;		//当前块的大小小于进程请求的大小,继续先后搜索
		}
		else p = p->m_next;			//当前块已经被占用,继续先后搜索
	}
	if (Error == 512)cout << "分配失败" << endl;
	else {
		if (Error == 0)q->m_flag = true;
		else {
			q->m_size -= (size + 1);	//从当前块中减去进程申请的大小
			block* temp = new block(true, size, q->m_next);	//新建一个进程块
			q->m_next = temp;			//添加到当前块的后面
		}
		PCB temp(name, size, addr2);
		lib.push_back(temp);
	}
}

 

 

 

 

 

3、最坏适应算法

最坏适应算法就是将程序放入主存中最不适合它的空闲区,即最大的空闲区内。在最坏适应算法中,空闲区是按大小递减顺序连接到一起的,因此,其队列指针总是指向最大空闲区,在进行分配时,总是从最大空闲区开始查寻。

代码:

 

void manage::worst() {

	cout << "输入进程名和大小:";
	string name; int size, addr1(0), addr2(0);
	cin >> name >> size;
	block *p(first), *q(nullptr);
	int Error(0);

	while (p != nullptr) {
		addr1 += (p->m_size + 1);
		if (p->m_flag == false) {		//当前块未被占用
			if (p->m_size >= size) {	//当前块的大小满足进程请求的大小
				if (p->m_size - size >= Error) {//当前块比之前块更大
					Error = p->m_size - size;	//计算偏差
					q = p;			//保存当前块的地址
					addr2 = addr1 - size - 1;
					p = p->m_next;	//指针后移
				}
				else p = p->m_next;	//和之前的块相比,之前的块更合适该进程
			}
			else p = p->m_next;		//当前块的大小小于进程请求的大小,继续先后搜索
		}
		else p = p->m_next;			//当前块已经被占用,继续先后搜索
	}
	if (Error == 0)cout << "分配失败" << endl;
	else {
		q->m_size -= (size + 1);		//从当前块中减去进程申请的大小
		block* temp = new block(true, size, q->m_next);	//新建一个进程块
		q->m_next = temp;				//添加到当前块的后面
		PCB temp1(name, size, addr2);
		lib.push_back(temp1);
	}
}

 

 

 

 

 

4、内存回收

在内存回收时应考虑四种情况:

假设回收区为r,上邻为f1(f1需搜索自由主存队列),下邻为f2(f2可直接计算)

A) f1空闲,f2已分配:r和f1合并

B) f1已分配,f2空闲:r和f2合并

C) f1空闲,f2空闲:r和f1、f2合并

D) f1已分配,f2已分配:r不和任何分区合并

代码:

 

void manage::free() {
	cout << "输入回收进程的名称:";
	string name;
	cin >> name;

	//在lib库中查找是否存在该进程
	vector<PCB>::iterator it = lib.begin();
	while (it != lib.end()){
		if (it->name == name)
			break;
		else it++;
	}
	//该进程不存在,直接提示并退出函数
	if (it == lib.end()) {
		cout << "该进程不存在" << endl;
		return;
	}
	//进程存在
	else {
		int addr(0); block *p(first);
		while (p != nullptr) {					//查找该进程所占用的内存块
			if (it->begin == addr)break;		//查找到该进程
			addr += (p->m_size + 1);
			p = p->m_next;
		}
		if (p == nullptr)cout << "未在内存中查找到该进程" << endl;
		else {
			p->m_flag = false;				//该内存块的状态更改为未占用
	
			//所回收的内存块后面存在空闲的内存块
			if (p->m_next != nullptr&&p->m_next->m_flag==false) {
				p->m_size += p->m_next->m_size;//该内存块的大小增加为为俩内存大小之和
				block *temp(p->m_next);
				p->m_next = p->m_next->m_next;	//更改指针指向
				delete temp;					//释放后一指针的空间
			}
			lib.erase(it);						//进程库中删除当前进程

			//所回收的内存块前面存在空闲的内存块
			block *q(first);
			//寻找到所回收的内存块前面的内存块
			while (q != nullptr) {
				//所回收的内存块前面存在空闲的内存块
				if (q->m_next==p&&q->m_flag == false) {	
					q->m_size += (p->m_size + 1);
					q->m_next = p->m_next;
					delete p;
					break;
				}
				q = q->m_next;
			}
		}
	}
}

 

 

 

 

 

(五)、程序运行情况

1、测试数据:初始值大小为512(分区描述器占一位,实际大小为511);

2、测试结果:

(1)、首次适应算法

 

(2)、最佳适应算法

 
 
 

 

(3)、最差适应算法

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值