伙伴系统优点:算法简单、速度快;缺点:由于归并伙伴而容易产生碎片。
可利用空间表的结构
#define m 16
typedef struct WORD_b{
WORD_b *llink;
int tag;
int kval;//块大小,值为2的幂次k
WORD_b *rlink;
OtherType other;
}WORD_b,head;//WORD内存字类型,结点的第一个字也称为head
typedef struct HeadNode{
int nodesize;//链表的的空闲块大小
WORD_b *first;//该立案表的表头指针
}FreeList[m+1];//表头向量类型,假设分配大小是2^m,从0次幂到m次幂
分配算法
2的k次幂有两种实现方式
①右移2<<k
②(int)pow(2,k)
WORD_b* AllocBuddy(FreeList &avail,int n){
for(k=0;k<=m && (avail[k].nodesize<n+1 ||!avail[k].first);++k);//查找满足分配要求的子表,在查找n的基础上+1是指针
if(k>m) return NULL;
else{
// 进行分配
pa=avail[k].first;//可分配的第一个结点
pre=pa->llink; //指向可分配子表的第一个结点(循环链表中的最后一个?)
suc=pa->rlink; //可分配子表的第二个结点,将作为本表的第一个结点
if(pa==suc) avail[k].first=NULL; //如果只有一个结点,分配后变成空表
else{//非空表,维护第一个和最后个结点的llink和rlink
pre->rlink=suc;
suc->llink=pre;
avail[k].first=suc;
}
//如果avail[k-1].nodesize<n-1说明这个结点要全部被分出去不用把分割的还回去
int i;
for(i=1;avail[k-i].nodesize>=n+1;++i){//将剩余块插入子表
pi=pa+2^(k-i);
pi->rlink=pi;
pi->llink=pi;
pi->tag=0;
pi->kval=k-i;
avail[k-i].first=pi;
}
pa->tag=1;
pa->kval=k-(--i);//--i使得没有分割时kval=k
}
return pa;
}
回收算法
自己写的回收算法,不知道对不对
WORD_b *MergeBuddy(FreeList &avail, WORD_b *p)
{ //p是大小为2^k的空闲分区
WORD_b *q = NULL;
while (true)
{
if (p % (2 << (p->kval + 1)) == 0)
{ //k是地址较低的伙伴
q = p + (2 << (p->kval));
if (q->tag == 0)
{ //伙伴空闲能够拼成大块
//在空闲大小为2^k的分区中删掉q
if (avail[p->kval].first == q)
avail[p->kval].first = NULL;
else
{
pre = q->llink;
q->rlink->llink = pre;
pre->llink = q;
}
//在2^(k+1)大小分区中添加p
p->kval++;
}
else
{ //如果伙伴不空闲,直接插入
if (!avail[p->kval].first)
avail[p->kval].first = p->llink = p->rlink = p;
else
{ // first->(p)->q->...->r
q = avail[p->kval].first;
r = q->llink;
p->llink = r;
r->rlink = p;
q->llink = p;
p->rlink = q;
}
break;
}
}
else
{ //k是地址较高的伙伴
q = p - (2 << (p->kval));
if (q->tag == 0)
{ //伙伴空闲能够拼成大块
//在空闲大小为2^k的分区中删掉q
if (avail[p->kval].first == q)
avail[p->kval].first = NULL;
else
{
pre = q->llink;
q->rlink->llink = pre;
pre->llink = q;
}
//在2^(k+1)大小分区中添加q
q->kval++;
p = q;
}
else
{ //如果伙伴不空闲,直接插入
if (!avail[p->kval].first)
avail[p->kval].first = p->llink = p->rlink = p;
else
{ // first->(p)->q->...->r
q = avail[p->kval].first;
r = q->llink;
p->llink = r;
r->rlink = p;
q->llink = p;
p->rlink = q;
}
break;
}
}
}
}
参考:
1.严氏数据结构 C语言教材
2.伙伴系统管理动态内存(理论部分内容)
3.算法8.2 伙伴系统-分配