首次适应算法实现主存的分配与回收

一、    实验内容

1、 内存分配。为了将一个新作业装入内存,必须按照一定的分配算法。本次实验,在内存分配时,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区为止。然后再按照作业的大小,从该分区中划分出一块内存空间,分配给请求者,余下的空闲分区仍留在空闲链中。若从链首直到链尾都不能找到一个能满足要求的分区,则表明系统中已没有足够大的内存分配给该进程,内存分配失败,返回。

2、 内存回收。将进程运行完毕需要释放的时候,系统根据回收取得首地址,从空闲区链中找到相应的插入点,此时可能出现以下四种情况之一。

I、回收区与插入点的前一个空闲分区F1相邻接,此时应将回收区与插入点的前一分区合并,不必为回收分区分配新表项,而只需修改前一分区F1的大小。

II、回收分区与插入点的后一空闲分区F2相邻接,此时也可将两分区合并,形成新的空闲分区,但用回收区的首地址作为新空闲区的首址,大小为两者之和。

III、回收区同时与插入点的前、后两个分区邻接,此时将三个分区合并,使用F1的表项和F1的首地址,取消F2的表项,大小为三者之和。

IV、回收区既不与F1邻接,又不与F2邻接。此时应为回收区单独建立一个新表项,填写回收区的首址和大小,并根据其首址插入到空闲链中的适当位置。

二、    数据结构的选择

1、 分区的结构体

typedef structpartition

{

int start;//始址

int length;//长度

int state;//状态

struct partition *next;

}PARTITION;

2、 空闲分区链依照首址从小到大排列,已分配分区链无序。

3、 没有进程控制块,每次执行插入新作业或者回收进程均由用户自行选择,进程ID由程序自动生成。

/*************************************************************************
	> File Name: lab5.c
	> Created Time: 2016年11月25日 星期五 15时24分15秒
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 50
typedef struct partition
{
	int start;//始址
	int length;//长度
	int state;//状态
	struct partition *next;
}PARTITION;
int memory;//内存大小
int count;//记录任务序列
PARTITION *spare = NULL, *assigned = NULL;//未分配表spare,已分配表assigned
int firstFit();//首次适应算法
int init();//初始化
void insertIntoSpare(PARTITION *);//将分区有序插入到未分配表
void insertIntoAssigned(PARTITION *);//将分区直接茶插入到已分配表尾
void deleteNullPartition();//检查并删除未分配表中长度为0的块
void memeoryState();//打印未分配表和已分配表的状态
void recoverMem(int);//回收内存

int main()
{
	//    printf("please input memory:");
	//    scanf("%d",&memory);
	memory = 120;//内存默认初始化为120
	init();
	firstFit();
	return 0;
}
//按照ppt上的描述进程初始化
int init()
{
	PARTITION *partition;
	partition = (PARTITION*)malloc(sizeof(PARTITION));
	partition->start = 15;
	partition->length = 23;
	partition->state = 0;
	partition->next = NULL;
	insertIntoSpare(partition);//插入链表
	partition = (PARTITION*)malloc(sizeof(PARTITION));
	partition->start = 48;
	partition->length = 20;
	partition->state = 0;
	partition->next = NULL;
	insertIntoSpare(partition);//插入链表
	partition = (PARTITION*)malloc(sizeof(PARTITION));
	partition->start = 80;
	partition->length = 30;
	partition->state = 0;
	partition->next = NULL;
	insertIntoSpare(partition);//插入链表

	partition = (PARTITION*)malloc(sizeof(PARTITION));
	partition->start = 0;
	partition->length = 15;
	partition->state = 1;
	partition->next = NULL;
	insertIntoAssigned(partition);//插入链表
	partition = (PARTITION*)malloc(sizeof(PARTITION));
	partition->start = 38;
	partition->length = 10;
	partition->state = 2;
	partition->next = NULL;
	insertIntoAssigned(partition);//插入链表
	partition = (PARTITION*)malloc(sizeof(PARTITION));
	partition->start = 68;
	partition->length = 12;
	partition->state = 3;
	partition->next = NULL;
	insertIntoAssigned(partition);//插入链表
	partition = (PARTITION*)malloc(sizeof(PARTITION));
	partition->start = 110;
	partition->length = 10;
	partition->state = 4;
	partition->next = NULL;
	insertIntoAssigned(partition);

	count = 4;//已经插入了4个进程
	return 1;
}
//将分区插入到已分配列表尾部
void insertIntoAssigned(PARTITION *partition)
{
	PARTITION *p;
	p = assigned;
	if (assigned == NULL)
	{
		assigned = partition;
	}
	else
	{
		while (p->next)
		{
			p = p->next;
		}
		p->next = partition;
	}
}
//将分区按照起始地址从小到大的顺序插入未分配链表
void insertIntoSpare(PARTITION *partition)
{
	PARTITION *p = NULL,*pre = NULL;
	p = pre = spare;
	if (spare == NULL)
	{
		spare = partition;
	}
	else if (p->start > partition->start)
	{
		partition->next = p;
		spare = partition;
	}
	else
	{
		p = p->next;
		while (p)
		{
			if (p->start > partition->start)
			{
				break;
			}
			pre = p;
			p = p->next;
		}
		partition->next = p;
		pre->next = partition;
	}
}
//打印内存分区状态
void memoryState()
{
	PARTITION *p = NULL;
	p = spare;
	printf("\n空闲分区表如下:\n");
	printf("始址\t长度\t标志\n");
	while (p)
	{
		printf("%dKB\t%3dKB\t", p->start, p->length);
		if (p->state == 0)
			printf("未分配\n");
		p = p->next;
	}

	p = assigned;
	printf("\n已分配分区表如下:\n");
	printf("始址\t长度\t标志\n");
	while (p)
	{
		printf("%dKB\t%3dKB\t", p->start, p->length);
		if (p->state)
		{
			printf("进程%d\n",p->state);
		}
		p = p->next;
	}
}
//删除长度为0的空白分区
void deleteNullPartition()
{
	PARTITION *pre, *p;
	p = pre = spare;
	if (p->length == 0)
	{
		spare = p->next;
		free(p);
	}
	else
	{
		while (p)
		{
			if (p->length == 0)
				break;
			pre = p;
			p = p->next;
		}
		if (p)
		{
			pre->next = p->next;
			free(p);
		}
	}
}
int firstFit()
{
	int request;
	int select;
	int recover;
	PARTITION *p;
	PARTITION *partition = NULL;
	while (1)
	{
		memoryState();
		printf("请选择(装入新作业:1  回收作业:2  结束:0):");
		scanf("%d",&select);
		if (select == 1)
		{
			printf("请输入新作业的长度:");
			scanf("%d", &request);
			count++;
			p = spare;
			while (p)//寻找合适的空白分区
			{
				if (p->length >= request)
				{
					break;
				}
				p = p->next;
			}
			if (p == NULL)//没有找到合适的空白分区
			{
				printf("您的胃口太大了,无法满足您的请求,请等待..\n");
				continue;
			}
			//分配分区
			partition = (PARTITION *)malloc(sizeof(PARTITION));
			partition->start = p->start;
			partition->length = request;
			partition->state = count;
			partition->next = NULL;
			insertIntoAssigned(partition);
			//处理被分配后的空白分区
			p->start = p->start + request;//起始地址发生变化
			p->length = p->length - request;//长度发生变化
			//有可能刚好被分配完,需要删除长度为0的空白分区
			deleteNullPartition();
		}//endif
		else if (select == 2)
		{
			printf("请输入要回收作业的序号:");
			scanf("%d",&recover);
			//回收
			recoverMem(recover);//回收算法
		}
		else if (select == 0)
		{
			break;
		}
	}
	return 1;
}
//回收作业并处理分区,考虑合并空白分区
void recoverMem(int ID)
{
	PARTITION *p = NULL,*pre=NULL;
	p = pre =  assigned;
	while (p)//寻找任务分区
	{
		if (p->state == ID)
		{
			break;
		}
		pre = p;
		p = p->next;
	}
	if (p == NULL)//没有指定分区
	{
		printf("内存中没有该作业!\n");
	}
	else
	{
		printf("已经找到要回收的进程%d\n",p->state);
		//将p从assigned中删除
		if (p == assigned)
			assigned = p->next;
		else
			pre->next = p->next;//从已分配列表中删除该任务
		//思路。。先检查是否和第一块空白区下相邻
		//之后检查是否和每一次上相邻,如果上相邻还需检查是否和下一个下相邻
		//是否和最后一个上相邻
		PARTITION *temp = spare;
		int flag = 0;
		if (p->start + p->length == temp->start)//和第一个下相邻
		{
			flag = 1;
			printf("正在回收的分区将与第一个空白分区合并\n");
			temp->start = p->start;
			temp->length += p->length;
		}
		else
		{
			while (temp->next)
			{
				if (temp->start + temp->length == p->start)//上相邻
				{
					flag = 1;
					if (p->start + p->length == temp->next->start)//下相邻
					{
						temp->length = temp->length + p->length + temp->next->length;
						PARTITION *tp = temp->next;
						temp->next = temp->next->next;
						free(tp);
					}
					else//只上相邻,不下相邻
					{
						temp->length = temp->length + p->length;
					}
					break;
				}
				if (p->start + p->length == temp->next->start)//仅下相邻
				{
					flag = 1;
					temp->next->start = p->start;
					temp->next->length += p->length;
					break;
				}
				temp = temp->next;
			}//endwhile
			if (flag == 0)//已经处理过了
			{
				if (temp->start + temp->length == p->start)
				{
					temp->length += p->length;
				}
				else
				{
					//中间区域,直接插入到空白列表中
					printf("和任何一个分区都不相邻,直接插入\n");
					PARTITION *partition = (PARTITION *)malloc(sizeof(PARTITION));
					partition->start = p->start;
					partition->length = p->length;
					partition->state = 0;
					partition->next = NULL;
					printf("插入--%d\n",partition->start);
					insertIntoSpare(partition);
				}
			}
		}
	}
	free(p);
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值