一、 实验内容
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);
}