OS_可变分区的存储管理:C++实现

一、实验目的:

  1. 加深对可变分区存储管理的理解;
  2. 提高用C语言编制大型系统程序的能力,特别是掌握C语言编程的难点:指针和指针作为函数参数;
  3. 掌握用指针实现链表和在链表上的基本操作。
    二、实验内容:
    参照教材P123-P125的内容,编写一个C程序,用char *malloc(unsigned size)函数向系统申请一次内存空间(如size=1000,单位为字节),用循环首次适应算法、最佳适应算法和最坏适应算法,模拟可变分区存储管理,实现对内存区的分配和回收管理。
    三、实验要求:
  4. 分配函数addr=(char *)lmalloc(unsigned size)和释放函数lfree(unsigned size,char *addr)的参数size和addr,要以键盘命令的形式输入,每次分配和释放后显示空闲分区表。
  5. 空闲分区表可采用结构数组的形式(最低要求)或双向链表的形式。

以上为实验的要求接下来来探讨如何的去实现,这里我用的是codeblocks加上notepad++,结合了很多人的代码,慢慢从小白蜕化····>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
物理分割

#include<stdio.h>#include<stdlib.h>#include<iostream>#include<iomanip>
我们引入这些库函数,要使用到malloc、cout、cin等等,我是从c转型的所以可能或许有些许的不同吧

假定我们的内存的分区可用空间为1000kb 那么我们需要定义一些预处理
#define maxsize 1000这个应该都可以看懂我就不过多的叙述了

定义数据结构
//结构的定义
typedef struct freePart{//空闲分区
long size;//分区的大小
long add;//分区的地址
int state;//状态
}elemType;
typedef struct twoNode{//双向链表
elemType data;
struct twoNode *pri;//前趋
struct twoNode *nex;//后驱
}twoNode,*linkTwoList;

typedef struct T{//排序的链表结构(单)
linkTwoList p;
struct T *next;
}T;

linkTwoList tou;//头节点
linkTwoList wei;//尾节点
T *headtou;


这些的定义我们可以参考一下书上的讲解,首先假设我们都实现了我们在main中需要怎么去写我们的代码呢?
我们得初始化我们的代码,因为我们的内存分区是由双向链表中的结构体实现的,所以我们首先得初始化我们的双向链表,头节点不需要指向任何东西,尾部的节点需要pri头节点,指向1000的空闲区,最后链接上一个null,这样我们的第一个就做好了。这个是我们的想法,具体的实现,之后再讲解。
当我们初始化完了之后我们会想着去显示在控制台上,那么我们也可以将我们的显示给定义为一个函数(方法),那么如何的去实现呢?
我们之前并未说明分区号因为我们是从0开始让它自动的递加,然后显示我们链表中的信息即可,如何显示我相信学过都会。。

我们可以让用户输入想要使用的算法序号,在request函数中作为参数传递
接下来我们可以设置一个switch语句,我们首先要明白这些算法都是分配的算法我们可以将分配放置在一个reques函数中,在free函数中进行回收,
那么
我们可以使用一个变量1为分配,2为回收,3为退出。根据用户输入的情况,选择分配的话我们进入到request函数中,如果选择回收我们就进入到free函数中,在进入的时候我们还要确定一点,我们要回收的分区号是多少,我们之前是让它自动的累加得到的分区号,所以是n-1,因为从0开始嘛,当我们这些做好了之后,我们的main也就完成了。

接下来我们进入我们的request函数中去,这个函数的主要功能是分配,我们之前让用户已经选择了使用哪个算法,参数传递过来之后我们得让用户输入要分配多少kb的空间,使用switch选择,将用户输入的空间size作为每个算法的参数进行传递即可

接下来就着重的讲解各个算法:因为第一次写这种讲解类,所以就比较的文字性了,待我学会可视化,图表一定安排上

循环首次适应算法(NF)

      算法的讲解:我们可以这样理解,从我们的分区链表中去循环的查找,如果有空闲且大小刚好是符合我们的申请的需求,那么直接将该块的状态置为忙,就可以了;如果有空闲且大于我们需要申请的分区,我们就让我们申请的分区的那个块在这个空闲分区的前面,因为是双向链表,所以我们一定要注意链接,将后者的data.add赋值给我们申请的那个块的add,将我们原本的add+申请的size即可,大小size就减去申请的size即可,两个条件都不满足我们就继续向后查找,如果查找不到,我们就返回错误,没找到合适的块,不能进行分配。

代码附上

int NF(int rsize){
	linkTwoList temp = (linkTwoList)malloc(sizeof(twoNode));
	temp->data.size=rsize;
	temp->data.state=busy;
		static twoNode *p;
		p=tou->nex;
	while(p){
		//刚好有空闲且满足需求的块,将状态置为忙即可
		if(p->data.state==free && p->data.size==rsize){
			p->data.state=busy;
			return ok;
			break;
		}
		//如果有空闲且比较大的块,将新的分区放在p前
		if(p->data.state==free && p->data.size>rsize){
			temp->pri=p->pri;
			temp->nex=p;
			temp->data.add=p->data.add;
			p->pri->nex=temp;
			p->pri=temp;
			p->data.add=temp->data.add+temp->data.size;
			p->data.size-=rsize;
			return ok;
			break;
		}
		p=p->nex;
	}
	return error;
}

接下来是最佳适应算法的讲解
算法的讲解如下:因为是最佳适应,所以我们要寻找空闲区将他们排队,空闲区递增就是最佳,递减就是最坏,所以,我们可以独立一个sort函数将我们这个链表进行排序,带一个参数,1为最佳,2为最坏就可以满足,关于sort函数因为比较的基本,后续考虑是否放上来。

  我们找到找到大于的空闲分区,没有就返回error有就需要判断是刚刚好还是大于,刚刚好直接修改状态,否则跟第一个一样,将它放置在前面

代码附上

int sort(int n){//排序  关于最佳最坏  1为最佳 2为最坏 递增递减  因为headtou是全局变量 所以
		//当我们穿起来了所有的空闲区就可以进行分配了
		//因为q就是tou节点的替身,所以我们在改变headtou中的p时,其实也是在改变tou,他们本来
		//就指向同一链表
	headtou = (T*)malloc(sizeof(T));
	linkTwoList q = tou;
	T *i = headtou;

	if(tou->nex == wei){//如果是空的,将其放置到由headtou指向的T链表中
		T *j = (T*)malloc(sizeof(T));
		headtou->next = j;
		j->p = wei;
		j->next=NULL;
	}
	else{
		while(q){
			if(q->data.state==free){
				T *j = (T*)malloc(sizeof(T));
				j->p=q;
				i->next=j;
				i=i->next;
				q=q->nex;
			}
			else q=q->nex;
		}
		i->next=NULL;//将所有的空闲区由headtou链接起来
		if(n==1){//排序,最佳适应算法 最小的在最上
			for(i=headtou->next;i!=NULL;i=i->next){
					for(T *j = i->next;j!=NULL;j=j->next){
						if(i->p->data.size > j->p->data.size){
							q=j->p;
							j->p=i->p;//交换value
							i->p=q;
						}
					}
			}
		}
		else{//最坏适应算法 最大的在最上
			for(i=headtou->next;i!=NULL;i=i->next){
				for(T *j = i->next;j!=NULL;j=j->next){
					if(i->p->data.size < j->p->data.size){
						q=j->p;
						j->p=i->p;
						i->p=q;
					}
				}
			}
		}
	}
	return ok;
}
//最佳适应算法
int BF(int rsize){
	sort(1);
	T *k = headtou->next;

	linkTwoList temp = (linkTwoList)malloc(sizeof(twoNode));
	temp->data.size=rsize;
	temp->data.state=busy;

	while(k->p->data.size<rsize)k=k->next;//找大于的空闲区
	if(k==NULL) return error;//无这种空闲区
		else if(k->p->data.size==rsize){//刚刚好
			k->p->data.state=busy;
			return ok;
			}
				else{
					int ch=k->p->data.size - rsize;
					temp->pri=k->p->pri;
					temp->nex=k->p;
					temp->data.add=k->p->data.add;
					k->p->pri->nex=temp;
					k->p->pri=temp;
					k->p->data.add+=rsize;
					k->p->data.size=ch;
					return ok;
				}
	return ok;

}

关于最坏就是最佳的相反所以就不在此多叙述了

关于回收,根据我们传入的分区号,我们可以区分三种情况
://如果要分配的分区的前面不是头节点且是空闲的。
//合并两个分区,并且使得p指向新的空闲分区
//如果要释放的分区的后一个分区也是空闲的那么我们就将其合并
//如果要释放的分区的后一个分区是最后一个空闲分区,合并后链接上NULL
最后的代码就不附上了,留点给看官自己思考,第一个实验就到此结束!!!因为第一次写,多有借鉴与瑕疵,敬请原谅!

原文地址:https://www.cnblogs.com/hgao/p/13062611.html