码迷,mamicode.com
首页 > 其他好文 > 详细

动态分区分配

时间:2016-01-07 01:26:01      阅读:354      评论:0      收藏:0      [点我收藏+]

标签:动态分区分配

#define _CRT_SECURE_NO_WARNINGS 1

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

enum STATE 
{ 
	Free,
	Busy
};

struct subAreaNode 
{
	int addr;             // 起始地址
	int size;              // 分区大小
	int taskId;        // 作业号
	STATE state;             // 分区状态
	subAreaNode *pre;     // 分区前向指针
	subAreaNode *nxt;       // 分区后向指针
}subHead;

// 初始化空闲分区链
void intSubArea()
{
	// 分配初始分区内存
	subAreaNode *fir = (subAreaNode *)malloc(sizeof(subAreaNode));
	// 给首个分区赋值
	fir->addr = 0;
	fir->size = 1000;     // 内存初始大小
	fir->state = Free;
	fir->taskId = -1;
	fir->pre = &subHead;
	fir->nxt = NULL;
	// 初始化分区头部信息
	subHead.pre = NULL;
	subHead.nxt = fir;
}

// 首次适应算法
int firstFit(int taskId, int size)
{
	subAreaNode *p = subHead.nxt;
	while (p != NULL)
	{
		if (p->state == Free && p->size >= size)
		{
			// 找到要分配的空闲分区
			if (p->size - size <= 10)
			{
				// 整块分配
				p->state = Busy;
				p->taskId = taskId;
			}
			else {
				// 分配大小为size的区间
				subAreaNode *node = (subAreaNode *)malloc(sizeof(subAreaNode));
				node->addr = p->addr + size;
				node->size = p->size - size;
				node->state = Free;
				node->taskId = -1;
				// 修改分区链节点指针
				node->pre = p;
				node->nxt = p->nxt;
				if (p->nxt != NULL)
				{
					p->nxt->pre = node;
				}
				p->nxt = node;
				// 分配空闲区间
				p->size = size;
				p->state = Busy;
				p->taskId = taskId;
			}
			printf("内存分配成功!\n");
			return 1;
		}
		p = p->nxt;
	}
	printf("找不到合适的内存分区,分配失败...\n");
	return 0;
}

// 最佳适应算法
int bestFit(int taskId, int size)
{
	subAreaNode *tar = NULL;
	int tarSize = 1000 + 1;
	subAreaNode *p = subHead.nxt;
	while (p != NULL)
	{
		// 寻找最佳空闲区间
		if (p->state == Free && p->size >= size && p->size < tarSize) {
			tar = p;
			tarSize = p->size;
		}
		p = p->nxt;
	}
	if (tar != NULL) {
		// 找到要分配的空闲分区
		if (tar->size - size <= 10)
		{
			// 整块分配
			tar->state = Busy;
			tar->taskId = taskId;
		}
		else
		{
			// 分配大小为size的区间
			subAreaNode *node = (subAreaNode *)malloc(sizeof(subAreaNode));
			node->addr = tar->addr + size;
			node->size = tar->size - size;
			node->state = Free;
			node->taskId = -1;
			// 修改分区链节点指针
			node->pre = tar;
			node->nxt = tar->nxt;
			if (tar->nxt != NULL) 
			{
				tar->nxt->pre = node;
			}
			tar->nxt = node;
			// 分配空闲区间
			tar->size = size;
			tar->state = Busy;
			tar->taskId = taskId;
		}
		printf("内存分配成功!\n");
		return 1;
	}
	else
	{
		printf("找不到合适的内存分区,分配失败...\n");
		return 0;
	}
}


int freeSubArea(int taskId)     // 回收内存
{
	int flag = 0;
	subAreaNode *p = subHead.nxt, *pp;
	while (p != NULL)
	{
		if (p->state == Busy && p->taskId == taskId)
		{
			flag = 1;
			if ((p->pre != &subHead && p->pre->state == Free)
				&& (p->nxt != NULL && p->nxt->state == Free))
			{
				// 情况1:合并上下两个分区
				// 先合并上区间
				pp = p;
				p = p->pre;
				p->size += pp->size;
				p->nxt = pp->nxt;
				pp->nxt->pre = p;
				free(pp);
				// 后合并下区间
				pp = p->nxt;
				p->size += pp->size;
				p->nxt = pp->nxt;
				if (pp->nxt != NULL) 
				{
					pp->nxt->pre = p;
				}
				free(pp);
			}
			else if ((p->pre == &subHead || p->pre->state == Busy)
				&& (p->nxt != NULL && p->nxt->state == Free)) 
			{
				// 情况2:只合并下面的分区
				pp = p->nxt;
				p->size += pp->size;
				p->state = Free;
				p->taskId = -1;
				p->nxt = pp->nxt;
				if (pp->nxt != NULL) 
				{
					pp->nxt->pre = p;
				}
				free(pp);
			}
			else if ((p->pre != &subHead && p->pre->state == Free)
				&& (p->nxt == NULL || p->nxt->state == Busy)) 
			{
				// 情况3:只合并上面的分区
				pp = p;
				p = p->pre;
				p->size += pp->size;
				p->nxt = pp->nxt;
				if (pp->nxt != NULL) 
				{
					pp->nxt->pre = p;
				}
				free(pp);
			}
			else
			{
				// 情况4:上下分区均不用合并
				p->state = Free;
				p->taskId = -1;
			}
		}
		p = p->nxt;
	}
	if (flag == 1)
	{
		// 回收成功
		printf("内存分区回收成功...\n");
		return 1;
	}
	else 
	{
		// 找不到目标作业,回收失败
		printf("找不到目标作业,内存分区回收失败...\n");
		return 0;
	}
}

// 显示空闲分区链情况
void showSubArea()
{
	printf("*********************************************\n");
	printf("**         当前的内存分配情况如下:        **\n");
	printf("*********************************************\n");
	printf("** 起始地址 | 空间大小 | 工作状态 | 作业号 **\n");
	subAreaNode *p = subHead.nxt;
	while (p != NULL)
	{
		printf("**-----------------------------------------**\n");
		printf("**");
		printf("  %3d  k  |", p->addr);
		printf("  %3d  k  |", p->size);
		printf("   %s   |", p->state == Free ? "Free" : "Busy");
		if (p->taskId > 0) 
		{
			printf("   %2d   ", p->taskId);
		}
		else
		{
			printf("        ");
		}
		printf("**\n");
		p = p->nxt;
	}
	printf("*********************************************\n");
}

int main()
{
	int option, ope, taskId, size;
	// 初始化空闲分区链
	intSubArea();
	// 选择分配算法
	while (1)
	{
		printf("\n\n");
		printf("\t****************请选择要模拟的分配算法******************\n");
		printf("\n\n");
		printf("\t \t        0    首次适应算法  \n");
		printf("\n\n");
		printf("\t \t        1    最佳适应算法  \n");
		printf("\n\n");
		printf("\t\t\t\t你的选择是:");
			scanf("%d", &option);
		if (option == 0)
		{
			printf("你选择了首次适应算法,下面进行算法的模拟\n");
			break;
		}
		else if (option == 1)
		{
			printf("你选择了最佳适应算法,下面进行算法的模拟\n");
			break;
		}
		else
		{
			printf("错误:请输入 0/1\n\n");
		}
	}
	// 模拟动态分区分配算法
	while (1)
	{
		printf("\n");
		printf("*********************************************\n");
		printf("**  1: 分配内存  2: 回收内存  0: 退出     **\n");
		printf("*********************************************\n");
		scanf("%d", &ope);
		if (ope == 0) break;
		if (ope == 1) {
			// 模拟分配内存
			printf("请输入作业号: ");
			scanf("%d", &taskId);
			printf("请输入需要分配的内存大小(KB): ");
			scanf("%d", &size);
			if (size <= 0) 
			{
				printf("错误:分配内存大小必须为正值\n");
				continue;
			}
			// 调用分配算法
			if (option == 0) 
			{
				firstFit(taskId, size);
			}
			else 
			{
				bestFit(taskId, size);
			}
			// 显示空闲分区链情况
			showSubArea();
		}
		else if (ope == 2)
		{
			// 模拟回收内存
			printf("请输入要回收的作业号: ");
			scanf("%d", &taskId);
			freeSubArea(taskId);
			// 显示空闲分区链情况
			showSubArea();
		}
		else 
		{
			printf("错误:请输入 0/1/2\n");
		}
	}
	printf("分配算法模拟结束\n");
	system("pause");
	return 0;
}


动态分区分配

标签:动态分区分配

原文地址:http://iynu17.blog.51cto.com/10734157/1732270

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!