设计六 我假装这是可变分区存储管理算法

1 设计内容 
通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解,熟悉可变分区存储管理的内存分配和回收。
设计一个可变式分区分配的存储管理方案。并模拟实现分区的分配和回收过程。对分区的管理法采用下面两种算法之一:首次适应算法、最佳适应算法,必须建立空闲分区表和已分配分区表,回收算法考虑以下四种情况:
回收区与插入点的前一个空闲分区相邻接;
回收区与插入点的后一个空闲分区相邻接;
回收区同时与插入点的前、后两个分区相邻接;
回收区不与任何空闲区邻接;
2 分析设计
可变分区存储管理方式在程序装入内存之前并不预先建立分区,而是在程序运行时根据程序对内存空间的需要,动态的建立内存分区。
对分区的管理法采用最佳适应算法。
2.1算法原理
最佳适应算法:在空闲分区链上,找到大于待载入程序大小的所有空闲区,再在里面把最小的空闲区分配给带载入程序;如果所有空闲区都不能满足带载入程序所需大小,则分配失败。
回收算法:内存的回收即是在程序运行完之后退出内存,把该内存空间及时回收,以便重新分配给需要的程序。主要考虑四种情况:
回收区只与上空闲分区相邻接:将这两个区域合并成一个新空闲分区,新空闲分区的起始地址为上空闲分区起始地址,大小为回收区和上空闲分区之和,同时修改相应的数据结构。
回收区只与下空闲分区相邻接:将这两个区域合并成一个新空闲分区,新空闲分区的起始地址为回收区起始地址,大小为回收区和下空闲分区之和,同时修改相应的数据结构。
回收区同时与插入点的前、后两个分区相邻接:将这三个区域合并成一个新空闲分区,新空闲分区的起始地址为上空闲分区起始地址,大小为回收区,上空闲分区和下空闲分区之和,同时修改相应的数据结构。
回收区不与任何空闲区邻接:将回收区单独作为一个空闲分区,同时修改相应的数据结构。
2.2程序结构
该算法主要以分区系统函数subarea()统筹插入函数insert(),输入程序函数scandP(),最佳适应算法函数optimun(),时间流失模拟函数timego(),输出函数printL()和回收算法recycle()来实现,总内存在主函数main()中创建。
插入函数insert():待载入程序插入空闲分区的低地址端;
输出函数printL():输出总分区表,已分配分区表以及空闲分区表,按照地址递增输出;
输入程序函数scandP():选择该时段想输入的程序个数,按照最佳适应算法载入程序;
最佳适应算法函数optimun():检索所有空闲分区,如果有空闲分区大小和待载入程序的一样,直接把该分区分配给待载入程序;如果只有大于待载入程序大小的空闲分区,则在其中找到最小的那个空闲分区,把它分配给待载入程序;如果没有满足大小的空闲分区,则反馈为分配失败。
回收算法recycle():按照地址递增检索所有已载入内存的程序,如果程序达到了所需的时间,则把它回收,回收分四种情况。
时间流失模拟函数timego():已载入内存的所有程序所需时间减一;
分区系统函数subarea():进入循环:输入该时段的程序,模拟时间流逝,回收,检查载入失败的程序是否可以被满足,输出分区表。
主函数main():创建总内存,启动分区系统。
2.3数据结构
设定总内存MAXS为500KB
定义分区单元结构体:
typedef struct node{ //定义分区单元
int ID; //程序号
int START; //起始地址
int SIZE; //大小
char STATE; //状态(已分配为‘P’或空闲为‘L’)
int NEEDTIME; //如果是已分配分区 则有 还需占用时间
struct node * next,* prior; //prior是前驱指针,next是后置指针
}SUBAREA;
定义内存分区双链表的头指针:
SUBAREA *ALL=NULL; //内存分区链的头指针
定义收集分配失败程序的数组和标识:
int get[100][2]; //程序集 用来记录未载入的程序
int g=0; //分配失败程序标识
2.4程序流程图
最佳适应算法流程图:
在这里插入图片描述
回收算法流程图:
在这里插入图片描述
2.5关键代码
插入函数insert():
void insert(SUBAREA *p,int size,int time){ //插入内存分区链的函数
SUBAREA p1;
p1=(SUBAREA
)malloc(sizeof(SUBAREA));

p1->SIZE=size;                              //程序插入低地址端
p1->STATE='P';
p1->ID=id;
id++;
p1->START=p->START;
p1->NEEDTIME=time;

p->SIZE=p->SIZE-size;
p->START=p1->START+size;

if(p->prior==NULL){                         //如果p结点为头结点
	p1->next=p;
	p->prior=p1;
	p1->prior=NULL;
	ALL=p1;
}
else{
    p1->prior=p->prior;
    p->prior->next=p1;
 	p1->next=p;
 	p->prior=p1;
}

}

输出函数printL():
void printL(char f){ //输出分区表 'P’为已分配分区表,'L’为空闲分区表,'S’为所有分区表
SUBAREA *p;
p=ALL;

if(f=='S'){
	int i=1; 
	cout<<"                            总分区表:"<<endl;
	cout<<"_________________________________________________________________"<<endl;
	cout<<"\t分区号    |"<<"\t起始地址(KB)  |"<<"\t大小(KB)  |"<<"\t状态     |"<<endl;
	while(p!=NULL){
		if(p->STATE=='P'){
		    cout<<"\t"<<i<<"\t  |"<<"\t"<<p->START<<"\t      |"<<"\t"<<p->SIZE<<"\t  |"<<"\t"<<p->STATE<<p->ID<<"\t |"<<endl;	    
		}
		else if(p->STATE=='L'){
		    cout<<"\t"<<i<<"\t  |"<<"\t"<<p->START<<"\t      |"<<"\t"<<p->SIZE<<"\t  |"<<"\t"<<p->STATE<<"\t |"<<endl;
		}
		i++;
		p=p->next;
	}
	cout<<"__________________|___________________|___________|______________|"<<endl<<endl;
}
else if(f=='P'){
	int j=1;
	cout<<"                         已分配分区表:"<<endl;
	cout<<"________________________________________________________________________________"<<endl;
	cout<<"\t分区号    |"<<"\t起始地址(KB)  |"<<"\t大小(KB)  |"<<"\t状态     |"<<"\t时间\t|"<<endl;
	while(p!=NULL){
		if(p->STATE=='P'){
		    cout<<"\t"<<j<<"\t  |"<<"\t"<<p->START<<"\t      |"<<"\t"<<p->SIZE<<"\t  |"<<"\t"<<p->STATE<<p->ID<<"\t |";
			cout<<"\t"<<p->NEEDTIME<<"\t|"<<endl;
		    j++;
		}
		p=p->next;
	}
	cout<<"__________________|___________________|___________|______________|______________|"<<endl<<endl;
}
else if(f=='L'){
	int k=1;
	cout<<"                          空闲分区表:"<<endl;
	cout<<"_________________________________________________________________"<<endl;
	cout<<"\t分区号    |"<<"\t起始地址(KB)  |"<<"\t大小(KB)  |"<<"\t状态     |"<<endl;
	while(p!=NULL){
		if(p->STATE=='L'){
		    cout<<"\t"<<k<<"\t  |"<<"\t"<<p->START<<"\t      |"<<"\t"<<p->SIZE<<"\t  |"<<"\t"<<p->STATE<<"\t |"<<endl;
		    k++;
		}
		p=p->next;
	}
	cout<<"__________________|___________________|___________|______________|"<<endl<<endl;
}

}
输入程序函数scandP():
void scandP(){ //载入一批程序 大小和时间
int s,t,i,n;
cout<<"请选择在这个时长载入程序的个数: ";
cin>>n;

if(n!=0){
    for(i=1;i<=n;i++){
	    cout<<"请输入第"<<i<<"个程序所需内存的大小SIZE和需要时间NEEDTIME:"<<endl;
	    cin>>s>>t;
	    optimun(s,t);
	}

    cout<<endl<<"-----------------------------载入完毕-----------------------------"<<endl<<endl;
    printL('S');
	printL('P');
	printL('L');
}
else
	cout<<"在这个时长不载入程序!"<<endl;

}
最佳适应算法函数optimun():
void optimun(int size,int time){ //最佳适应算法
SUBAREA *p1,*p2;
int a=1,min=MAXS+1,area=0;
p1=ALL;
p2=ALL;

while(p1!=NULL){

	if(p1->STATE=='L'){
	    if(p1->SIZE==size){            //该空闲区等于程序需求
	    	p1->NEEDTIME=time;
			p1->ID=id;
			p1->STATE='P';
			id++;
			a=0;
	    	break;
		}
	    else if(p1->SIZE>size){         //找到大于要求的各空闲区的最小值
	    	if(p1->SIZE<min){
		    	area=p1->START;
		    	min=p1->SIZE;
			}
	    	p1=p1->next;
		}
    	else if(p1->SIZE<size)          //小于
			p1=p1->next;
	}
	else
		p1=p1->next;                     
}

while(min!=MAXS+1&&a==1){               //在链表中找到刚才的空闲区
	if(p2->START==area){
		insert(p2,size,time);
		break;
	}
	p2=p2->next;
}

if(a==1&&min==MAXS+1){
	cout<<"!!!所有空闲分区的大小都不能满足要求,此次分配失败!!!"<<endl<<endl;
	g++;                 //失败数加1
	fail(g,size,time);   //记录
}
else
	cout<<"~已分配程序~ 程序名为:"<<"P"<<id-1<<endl<<endl;

}
回收算法recycle():
void recycle(){ //回收算法
SUBAREA *p,*p1;
p=ALL;

cout<<endl<<"--------------------正在对已完成程序进行回收处理-----------------"<<endl<<endl;

while(p!=NULL){
	p1=(SUBAREA*)malloc(sizeof(SUBAREA));
	if(p->STATE=='P'&&p->NEEDTIME==0&&p->prior!=NULL&&p->next!=NULL){  //此结点不是首尾位置

		if(p->prior->STATE=='L'&&p->next->STATE=='L'){                 //上下分区都是空闲分区
			p1->START=p->prior->START;
			p1->SIZE=p->SIZE+p->prior->SIZE+p->next->SIZE;
			p1->NEEDTIME=0;
			p1->STATE='L';

			if(p->next->next!=NULL){                                   //它的下分区是否 尾结点
				p1->next=p->next->next;
				p->next->next->prior=p1;
			}
			else
				p1->next=NULL;

			if(p->prior->prior!=NULL){                                 //它的上分区是否 首结点
				p1->prior=p->prior->prior;
			    p->prior->prior->next=p1;
			}
			else{
				p1->prior=NULL;
				ALL=p1;
			}
		}
		else if(p->prior->STATE=='L'&&p->next->STATE=='P'){            //上分区是空闲分区,下分区是已分配分区
			p1->START=p->prior->START;
			p1->SIZE=p->prior->SIZE+p->SIZE;
			p1->NEEDTIME=0;
			p1->STATE='L';

			if(p->prior->prior!=NULL){
				p1->prior=p->prior->prior;
			    p->prior->prior->next=p1;
			}
			else{
				p1->prior=NULL;
				ALL=p1;
			}

		    p1->next=p->next;
			p->next->prior=p1;
		}
		else if(p->prior->STATE=='P'&&p->next->STATE=='L'){            //下分区是空闲分区,上分区是已分配分区
			p1->START=p->START;
			p1->SIZE=p->SIZE+p->next->SIZE;
			p1->NEEDTIME=0;
			p1->STATE='L';

			p1->prior=p->prior;
			p->prior->next=p1;

			if(p->next->next!=NULL){
				p1->next=p->next->next;
		        p->next->next->prior=p1;
			}
			else
				p1->next=NULL;
		}
		else if(p->prior->STATE=='P'&&p->next->STATE=='P'){            //上下都不是
			p->STATE='L';
			p->ID=NULL;
		}
	}
	else if(p->STATE=='P'&&p->NEEDTIME==0&&p->prior==NULL&&p->next!=NULL){   //此结点是 首结点 
		if(p->next->STATE=='L'){
			p1->START=p->START;
			p1->SIZE=p->SIZE+p->next->SIZE;
			p1->NEEDTIME=0;
			p1->STATE='L';

			if(p->next->next!=NULL){
				p1->next=p->next->next;
		        p->next->next->prior=p1;
			}
			else
				p1->next=NULL;
			p1->prior=NULL;
			ALL=p1;
		}
		else{
			p->STATE='L';
			p->ID=NULL;
		}
	}
	else if(p->STATE=='P'&&p->NEEDTIME==0&&p->next==NULL&&p->prior!=NULL){   //此结点是 尾结点
		if(p->prior->STATE=='L'){
			p1->START=p->prior->START;
			p1->SIZE=p->prior->SIZE+p->SIZE;
			p1->NEEDTIME=0;
			p1->STATE='L';

			if(p->prior->prior!=NULL){
				p1->prior=p->prior->prior;
			    p->prior->prior->next=p1;
			}
			else{
				p1->prior=NULL;
				ALL=p1;
				p1->next=NULL;
			}
		}
		else {
			p->STATE='L';
			p->ID=NULL;
		}
	}
	else if(p->STATE=='P'&&p->NEEDTIME==0&&p->next==NULL&&p->prior==NULL)    //同时为首尾结点 即只有一个分区
		p->STATE='L';

 	p=p->next;
}
cout<<endl<<"-----------------------------完成回收----------------------------"<<endl<<endl;
printL('S');
printL('P');
printL('L');

}
时间流失模拟函数timego():
void timego(){ //模拟时间流逝函数
SUBAREA *p;
p=ALL;

while(p!=NULL){
	if(p->STATE=='P')
	    p->NEEDTIME-=1;
	p=p->next;
}
cout<<endl<<"--------------------------一个时长过去了-------------------------"<<endl<<endl;

}
分区系统函数subarea():
void subarea(){ //分区系统
while(1){
int gett[100][2];
scandP(); //选择载入的程序
timego(); //时间流逝
recycle(); //回收

	if(g!=0){
	    for(int o=1;o<=g;o++){
		    gett[o][0]=get[o][0];
		    gett[o][1]=get[o][1];
	    	get[o][0]=0;
	    	get[o][1]=0;
		}

	    g=0;
	    cout<<"检查载入失败的程序是否能被满足条件:"<<endl;

    	for(int m=1;m<o;m++){
	    	cout<<"分配失败程序队列第"<<m<<"个程序时间和大小:"<<gett[m][0]<<" "<<gett[m][1]<<endl;
	    	optimun(gett[m][0],gett[m][1]);
		}

	    if(g!=o-1){
	    	printL('S');
	    	printL('P');
	    	printL('L');
		}
	}
}

}
主函数main():
int main(){
SUBAREA FI;
FI=(SUBAREA
)malloc(sizeof(SUBAREA)); //创建第一个分区 即总内存
FI->START=0;
FI->SIZE=MAXS;
FI->NEEDTIME=0;
FI->STATE=‘L’;
FI->next=ALL;
FI->prior=ALL;
ALL=FI;

subarea();                             //启动分区系统

return 0;

}
3 开发环境
Windows 7 + VC++6.0
4 运行结果及分析
先输入三个程序大小好时间分别为:
200 1
250 3
45 1
见图6.4.1
在这里插入图片描述
图6.4.1
再输入一个程序大小和时间分别为:
45 1
见图6.4.2
在这里插入图片描述
图6.4.2
可以看到,分区分配按照最佳适应算法实现。
5 心得体会
这次为期三周的实习,真真正正让我体会到了代码的无限乐趣!
原本打算用这学期新学的java来实现进程调度,但是不够熟悉,只好还是用更熟悉的c语言来打。经过不断地磨合修改代码,从课本学习对照,上网查资料,第一周已经过了两天,而我得出了我的进程调度的简化版本,真的很满足当时。但是陆陆续续出了很多的问题却找不到解决办法,和小伙伴一起探讨了一段时间,修改了很多bug,最终把界面优化美化后看起来很舒服,后面又依据实习要求完成了可变分区存储管的实现,心中莫名有些成就感。
在实习期间,通过和小伙伴的讨论和上网学习,真正的学到了很多东西。从刚开始的为了完成任务而学习变成了因为兴趣而学习,养成了很好的学习习惯。这次实习令人很满足,也很令人回味。

参考文献
1.胡元义,黑新宏等.《操作系统原理》.北京:电子工业出版社,2018.08:177-180
2.耿国华等.《数据结构(第二版)》.北京:高等教育出版社,2015.07(2018.02重印):60-70

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值