动态分区分配
一、实验目标
开发一个C语言程序实现内存空间管理的动态分区分配方案。
二、实验原理
动态分区分配:根据进程的实际需要,动态地创建分区为之分配内存空间,在实现动态分区分配时,将涉及分区分配中所使用的数据结构,分区分配算法和分区的分配与回收操作等问题。
1) 分区分配中的数据结构
空闲分区表:一个数据表,用于记录每个空闲块的情况,如起始地址、大小、使用情况等;
空闲分区链表:把所有的空闲分区链接成一个链表,便于内存空间查看与分配回收。
2) 内存分配过程
利用分配算法找到满足要求的内存块,设请求的内存大小为size:
若找到的空闲分区的大小等于size,完全分配;
若找到的空闲分区大小大于size,且一分为二后,剩余大小小于1K,则不再分割,作为整体进行分配;否则一分为二,剩余部分仍然作为空闲分区存在;
若无满足要求空闲分区,则分配失败
3) 分配算法
首次适应法:空闲分区按首地址递增次序组织,每次查找时从链首出发,寻找满足要求的内存块。
最佳适应法:空闲分区按空闲分区大小址递增次序组织,每次查找时从链首出发,寻找满足要求的最小内存块进行分配。
最坏适应法:空闲分区按空闲分区大小递减次序组织,每次查找时直接判断最大空闲分区是否满足要求。
4) 内存回收
根据释放区首址和大小,查找空闲分区表/链表,判断是否有相邻的空闲分区存在:
释放区与前空闲区相邻:将释放区与前空闲区合并为一个空闲区。其首址仍为前空闲区首址,大小为释放区大小与空闲区大小之和。
释放区与前后两个空闲区相邻:将这三个区合为一个空闲区,其首址为前空闲区首址,大小为这三个区大小之和,并取消原后空闲区表目。
释放区与后空闲区相邻:则把释放区合并到后空闲,首地址为释放区首地址,大小为二者大小之和。
释放区不与任何空闲区相邻:将释放区作为一个空闲区,将其大小和首址插入到空闲区表的适当位置。
实验目的或要求:通过本实验使我们深入理解计算机存储器管理的连续分配方式或离散分配方式的分页技术的思想与实现方法,使我们更好分析和掌握连续或分页实现内存管理的特点,达到对计算机学科基础实践能力、问题分析、设计、算法实现的专业核心能力的培养。
开发一个C语言程序实现内存空间管理的动态分区分配方案。根据进程的实际需要,动态地创建分区为之分配内存空间,在实现动态分区分配时,将涉及分区分配中所使用的数据结构,分区分配算法和分区的分配与回收操作等问题。设计分区分配中的数据结构,实现内存分配过程,使用首次适应法实现分配内存空间作用,并处理好各种内存回收中的各种情况,比如释放区与前空闲区相邻,释放区与前后两个空闲区相邻等等。
#include <stdio.h>
#include <stdlib.h>
int memory = 0; //存储空间的大小
int count = 0; //记录总的作业数
typedef struct Storage{
int number; //作业号
int start;
int last;
int size;
int state; //区分内存空间是已分配还是未分配 空闲为0
struct Storage *next;
}Storage;
int add(Storage *head,int number,int size){
Storage *add1 = head->next;
//遍历
while(add1 != NULL){
//找到大于或等于插入作业的空闲区
if(add1->number==-1 && add1->size>=size){
break;
}
add1 = add1->next;
}
if(add1 == NULL){
//未找到合适的空闲区
return 0;
}
//将空闲区划分为两个部分
int sizeOld = add1->size;
//存储作业
add1->number=number;
add1->size = size;
add1->state = 1;
add1->last = add1->start + size - 1;
//新空闲区部分
Storage *add2 = (Storage *)malloc(sizeof(Storage));
add2->number = -1;
add2->size = sizeOld - size;
add2->start = add1->last + 1;
if(add2->start >= memory - 1){
add1->next = NULL;
return 1;
}
add2->state = 0;
add2->last = add2->start + add2->size - 1;
add2->next = add1->next;
add1->next = add2;
return 1;
}
int deleted(Storage *head,int id){
Storage *del1 = head->next;
Storage *del2 = del1->next;
int temp1 = -1,temp2 = -1;
while(del1 != NULL){
if(id == del2->number){
temp1 = 0;
temp2 = 0;
//与前一个空闲区相邻
if(del1->state == 0){
temp1 = 1;
}
//与后一个空闲区相邻
if(del2->next->state == 0){
temp2 = 1;
}
break;
}
del1 = del1->next;
del2 = del2->next;
}
//讨论空闲区前后空闲区情况
//前后都是空闲区
if(temp1 == 1 && temp2 == 1){
del1->last = del2->next->last;
del1->size = del1->size + del2->size + del2->next->size;
del1->state = 0;
del1->number = -1;
del1->next = del2->next->next;
}
//前面是空闲区
else if(temp1 == 1){
del1->number = -1;
del1->size = del1->size + del2->size;
del1->state = 0;
del1->last = del2->last;
del1->next = del2->next;
}
//后面是空闲区
else if(temp2 == 1){
del2->number = -1;
del2->size = del2->size + del2->next->size;
del2->state = 0;
del2->last = del2->next->last;
del2->next = del2->next->next;
}
//前后都不是空闲区
else{
del2->number = -1;
del2->state = 0;
}
return 1;
}
//查看内存分配情况
void viewinformation(Storage *head){
Storage *p = head->next;
while(p != NULL){
if(0 == p->state){
printf("空闲区 \tstart = %d\tlast = %d\tsize = %d\n",p->start,p->last,p->size);
}
else{
printf("作业id = %d\tstart = %d\tlast = %d\tsize = %d\n",p->number,p->start,p->last,p->size);
}
p = p->next;
}
}
void firstview(){
printf("1: 为新作业分配内存\n");
printf("2: 回收作业释放内存\n");
printf("3: 查看内存分配情况\n");
printf("4:退出\n");
printf( "请输入操作: " );
}
int main(){
printf("请输入存储空间大小(单位K):");
scanf("%d",&memory);
//初始化
Storage *head = (Storage *)malloc(sizeof(Storage));
Storage *storage = (Storage *)malloc(sizeof(Storage));
head->next = NULL;
storage->number = -1;
storage->size = memory;
storage->start = 0;
storage->last = memory-1;
storage->state = 0;
storage->next = NULL;
head->next = storage;
while(1){
int chioce, id, size;
firstview();
scanf("%d", &chioce);
switch(chioce){
//四个选项,分别做不同的事情
case 1 : {
//分配新作业
printf("请输入作业id 和 作业大小size:\n");
printf("id = ");
scanf("%d",&id);
printf("size = ");
scanf("%d",&size);
if(add(head,id,size)){
printf("空间分配成功!\n");
//每分配一次空间,作业数加一
count++;
}
else{
printf("空间分配失败!\n");
}
break;
}
case 2 : {
//回收作业
printf("请输入回收作业的 id:");
scanf("%d",&id);
if(deleted(head,id)){
//回收成功
count--;
printf("作业回收成功!\n");
}
else{
//回收失败
printf("作业回收失败!\n");
}
break;
}
case 3 : {
//查看分配情况
viewinformation(head);
break;
}
case 4 : {
//退出程序
return 0;
}
}
}
return 0;
}