可变分区存储管理-循环首次适应法
文章目录
摘要
本次试验中,使用双向链表的数据结构,用 C 语言成功实现了可变分区存储管理中的循环首次适应法,实现了对内存区的分配和释放管理。并且考虑了很多分配和释放内存区时的错误,如分配时内存不足,释放越界,重复释放等问题,并给出了合适的解决办法。通过本次试验,可以加深理解可变分区存储管理与用指针和结构体实现双向链表和在链表上的基本操作。
算法思想和概要设计
算法思想
分配算法
程序采用循环首次适应法的思想,把空闲表设计成连接结构的循环队列,各空闲区仍按地址从低到高的次序登记在空闲区的管理队列中,同时设置一个起始查找指针,指向循环队列中的一个空闲区表项。
循环首次适应法分配时总是从起始查找指针所指的表项开始查找,第一次找到满足要求的空闲区时,就分配所需大小的空闲区,修改表项,并调整起始查找指针,使其指向队伍中被分配的后面那块空闲区。下次分配时就从新指向的那块空闲区开始查找。
释放算法
循环首次适应法的释放算法针对以下四种情况采取四种策略:
- 释放区与前空闲区相连:合并前空闲区和释放区构成一块大的新空闲区,并修改前空闲区表项的地址和大小属性。
- 与前空闲区和后空闲区都相连:将三块空闲区合并成一块空闲区,并修改前空闲区表项的地址和大小属性。
- 仅与后空闲区相连:与后空闲区合并,并修改后空闲区表项的地址和大小属性。
- 与前、后空闲区皆不相连:在前、后空闲区表项中间插入一个新的表项。
概要设计
主程序中,先向真实主存申请一块固定大小的内存,再用这块内存初始化空闲区双向链表。此时双向链表中只有一个表项,其前向指针与后向指针都指向自身,大小属性等于申请的内存的大小。之后用键盘输入指令来模拟程序向主存申请或释放内存。
初始化
双向链表中只有一个表项,其前向指针与后向指针都指向自身,大小属性等于申请的内存的大小,地址属性等于申请的内存的基地址。
分配
查找指针不断前移直到找到合适的空闲区。如果沿双向链表找了一圈仍未找到,就认为不存在合适的空闲区,拒绝分配并报错。
释放
由于使用了基地址,所以指令中输入相对地址进行释放。值得一提的是,释放时考虑了多个可能出现的错误,如重复释放已空闲区域,释放区位置与已存在的空闲区部分重合等问题。
数据结构与变量说明
双向链表的表项:
/*双向链表的定义*/
struct map
{
unsigned m_size; //空闲区大小
char *m_addr; //空闲区首地址
struct map *next, *prior; //后向指针与前向指针
};
全局指针
struct map *coremap; //链表起始指针
struct map *flag; //起始查找指针
源程序
链表结构体与全局变量的定义
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
//#include <malloc.h>
#define MEMSIZE 1000
/*双向链表的定义*/
struct map
{
unsigned m_size;
char *m_addr;
struct map *next, *prior;
};
struct map *coremap; //链表起始指针
struct map *flag; //起始查找指针
循环首次适应法的分配函数
/*循环适应的分配函数*/
char *lmalloc(unsigned size)
{
register char *a;
register struct map *bp;
bp = flag;
do
{
if(bp->m_size >= size)
{
a = bp->m_addr;
bp->m_addr += size;
flag = bp->next;
if((bp->m_size -= size) == 0) // 删除用光的空闲区项
{
bp->prior->next = bp->next;
bp->next->prior = bp->prior;
free(bp);
}
printf("Success: lmalloc size: %d, addr:%p\n", size, a); //分配空间成功
return(a);
}
bp = bp->next;
}while(bp != flag);
printf("Error: There is no appropriate memory to be allocated for the size!\n"); //分配空间失败
return(0);
}
循环首次适应法的释放函数
/* 循环首次适应的释放函数 */
char *lfree(unsigned size, char *aa)
{
struct map *bp;
char *a;
a = aa;
for(bp = coremap; bp->m_addr <= a; bp = bp->next);
if (bp->prior->m_addr + bp->prior->m_size >= a && a >= bp->prior->m_addr && bp->next != bp) /* 情况1,2 */
{
if(a + size > bp->m_addr + bp->m_size) // 防止向下溢出一整个空闲项
{
printf("Error: Release area out of bounds!\n");
return(0);
}
else if(bp->prior->m_addr + bp->prior->m_size > a + size) // 防止重复释放已空闲的区域
{
printf("Error: Already released!\n");
return(0);