数据结构-动态存储管理

本文探讨了动态存储管理中的内存回收系统,包括连续分配策略和可利用空间表的维护。介绍了边界标识法、伙伴系统及其分配与回收算法。同时,讨论了无用单元收集和存储紧缩在内存管理中的作用,强调了这些方法在解决内存碎片和提高内存利用率上的重要性。
摘要由CSDN通过智能技术生成

内存回收系统做法

  1. 一种策略是系统继续从高地址的空闲块中进行分配,不理会已经分配给用户的内存区是否空闲,直到分配无法进行,系统才去回收所有用户不再使用的空闲块,并重新组织内存将所有空闲的内存区连接在一起成为一个大的空闲块
  2. 另一种策略是用户一旦运行结束,便将它所占的内存区释放成为空闲块,每当新的用户请求分配内存时,系统巡视整个内存区的空闲块,并从中找出一个合适的分配之。为此,系统需建立一张记录所有空闲块的“可利用空间表”
  3. 可利用空间表一般为链表或者目录表 ,目录表包括:初始地址、空闲块大小、使用情况三项,链表的每个表结点表示一个空闲块,每次分配回收即是在可利用空间表中删除或插入结点。

可利用空间表及分配方法

只讨论链表,可利用空间表可称为存储池,三种情况:

  1. 系统运行期间所有用户请求分配的存储量大小相同,通常在系统开始运行时将内存区分割为大小相同的块,然后用指针链接成一个可利用空间表,请求内存时将第一个结点分配给程序,回收内存时在表头插入结点即可。
  2. 系统运行期间用户请求分配的存储量有若干种大小的规格,通常建立若干个可利用空间表,表内结点大小相同。此时分配与回收与第一种类似,只是在各自的可利用空间表中进行。两种额外情况:
  • 如果结点大小与请求分配的内存大小相同的链表空了,查询结点较大的链表,取出一个结点分配一部分内存,再将剩下的部分插入相应的链表中
  • 如果对应结点大小和大结点的链表都为空,不一定是内存满了,而是有可能经过多次分配之后,空闲区变成了多个小结点在其他链表中,此时应当重整内存,即"内存紧缩"
  1. 系统运行期间用户请求分配的存储量大小不固定,就将整个内存空闲区作为结点,分配时割出一个结点,这种情况下结点应当指明自身的大小,即有一个结点大小域

由于结点大小不同,故在分配时有一个问题,如果需要m大小的空间,可利用空间表中却有若干个不小于m的空闲块,该怎么分配:
(1) 首次拟合 从表头指针查找,找到的第一个大小不小于m的结点的一部分分配给用户。
(2) 最佳拟合 将可利用空间表中一个不小于m且最接近m的空闲块的一部分分配给用户,推荐按结点从小到大排序,回收时把释放的空闲块插入到合适的位置上区
(3) 最差拟合 将可利用空间表中不小于n且是链表中最大的空闲块的一部分分配给用户,此时结点应当从大到小排序,分配时只需从链表中删除第一个结点,并分配一部分给用户,剩余部分插入到合适位置。

最佳拟合法适用于请求分配的内存大小范围较广的系统。最差拟合每次从最大结点分配,最终结点大小趋于一致,适用于内存大小范围较窄的系统。

通过时间考虑:首次拟合分配时需查找可利用空间表,回收时插入到表头;最佳拟合无论分配回收都需要查找可利用空间表;最差拟合分配时直接表头分配,回收时查找

边界标识法

边界标识法是操作系统中用以动态分区分配的一种存储管理方法,系统将所有空闲块连接在一个双重循环链表结构的可利用空间表中。特点在于:

  1. 每个内存区头部和底部设标识,标识该区域是占用块还是空闲块,使得在回收用户释放的空闲块时易于判别在物理位置上与其相邻的内存内存区域是否为空闲块,以便合并空闲存储区

可利用空间表的结构

space指示存储单元,单元大小由head中的size域表示,以head和foot作为边界,head和foot中都有标志域tag,

typedef struct WORD
{
   
	union{
   
		WORD *llink;//指向前驱
		WORD *uplink;//指向本结点头部
	};
	int tag;//空闲占用标识
	int size;//块大小
	WORD *rlink;//指向后继结点
	OtherType other;//其他
}WORD,head,foot,*Space;

可利用空间表设置为双重循环链表,llink指向前驱,rlink指向后继,表中不设头节点,表头指针可以指向任意一个结点。

分配算法

首次拟合法,找到表头指针所指结点起在可利用空间表中查找,找到第一个容量不小于请求分配的存储量的空闲块就进行分配
(1)如果待分配块容量为m个字,每次分配分配n个字给用户,剩余m-n大小的结点仍然留在链表中,这样的话会剩余容量极小的块,但设定一个e,m-n<e时,就将m整块分配给用户,反之分配高地址的n个字给用户(避免修改指针)
(2) 如果每次分配都从表头指针开始找的话,会使得存储量小的结点密集在头指针附近,所以每次查找应当从不同结点开始查找,实现方法是使头指针指向刚分配过结点的后继结点

Space AllocBoundTag(Space &pav, int n)
{
   
	for(p=pav;p&&p->size<n&&p->rlink!=pav;p;p->rlink)//查找空闲块
		;
	if(!p||p->size<n)
		return nullptr;//找不到合适空闲块
	else
	{
   
		f=Footloc(p);
		pav=p->rlink;//让表头结点指向尾结点
		if(p->size-n<=e)
		{
   
			if(pav==p)//分配后变为空表
				pav=NULL;
			else
			{
   
				pav->llink=p->llink;//p结点整个分配,删除p结点,
				p->llink=p->rlink=pav;
			}
			p->tag=f->tag=1;//标识为使用块
		}
		else
		{
   
			f->tag=1;//分配块标识
			p-=n;//减去分配块大小
			f=Footloc(p);//切换到空闲块底部
			f->tag=0;
			f->uplink=p;
			p=f+1;//分配块头部
			p->size=n; p->tag=1;
			
		}
		return p;
	}
}

回收算法

若释放块头部地址为p 则p-1为左侧紧邻块地址,p+p->size为右侧紧邻块地址,检查这两个地址中tag就知道是否为空闲块,故有四种情况

(1) 左右均为占用块,即做简单插入

p->tag=0;Footloc(p)->uplink=p;Footloc(p)->tag=0;//设置空闲标识
if(!pav)
{
   
	pav=p->link=p->rlink=p;
}
else
{
   //双向链表
	q=pav->llink;
	p->rlink=pav;
	p->llink=q;
	q->rlink=pav->llink=p;
	pav=p;
}
p->tag=0;
Footloc(p)->uplink=p;
Footloc(p)->tag=0;
if(
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值