分类:
2011-12-16 20:43:02
原文地址:Uclibc中的malloc机制分析(三) 作者:xgr180
9: __heap_free_area_alloc (struct heap *heap,
struct heap_free_area *fa, size_t size)
该函数从fa所表示的空闲中,分配size大小的内存
实现如下:
extern inline size_t
__heap_free_area_alloc (struct heap *heap,
struct heap_free_area *fa, size_t size)
{
size_t fa_size = fa->size;
//如果该空闲区剩余的内存太少。将它全部都分配出去
//参考HEAP_MIN_FREE_AREA_SIZE的分析
if (fa_size < size + HEAP_MIN_FREE_AREA_SIZE)
/* There's not enough room left over in FA after allocating the block, so
just use the whole thing, removing it from the list of free areas. */
{
//将fa从heap中删除
__heap_delete (heap, fa);
/* Remember that we've alloced the whole area. */
size = fa_size;
}
else
/* Reduce size of FA to account for this allocation. */
fa->size = fa_size - size;
return size;
}
从上面可以看出,分配内存时,只是简单的缩少了空闲区的长度。
10: __heap_alloc (heap, &size);
从堆heap中分配size字节的内存
实现如下:
void *
__heap_alloc (struct heap *heap, size_t *size)
{
struct heap_free_area *fa;
size_t _size = *size;
void *mem = 0;
//根据HEAP_GRANULARITY 对齐 sizeof(double)
_size = HEAP_ADJUST_SIZE (_size);
//如果要分配的内存比FA结构还要小,那就调整它为FA大小
if (_size < sizeof (struct heap_free_area))
/* Because we sometimes must use a freed block to hold a free-area node,
we must make sure that every allocated block can hold one. */
_size = HEAP_ADJUST_SIZE (sizeof (struct heap_free_area));
HEAP_DEBUG (heap, "before __heap_alloc");
/* Look for a free area that can contain _SIZE bytes. */
//遍历堆中的FA,找出有合适大小的空闲区
for (fa = heap->free_areas; fa; fa = fa->next)
if (fa->size >= _size)
{
/* Found one! */
mem = HEAP_FREE_AREA_START (fa);
//从该空间中分得内存。这函数前面已经分析过了
*size = __heap_free_area_alloc (heap, fa, _size);
break;
}
HEAP_DEBUG (heap, "after __heap_alloc");
//返回地址
return mem;
}
11:__heap_free (struct heap *heap, void *mem, size_t size)
照语义上的理解是释放掉从mem开始的size大小的内存。换句话说,就是把从从mem开始的,size大小的内存段,映射回heap。
它的实现如下:
struct heap_free_area *
__heap_free (struct heap *heap, void *mem, size_t size)
{
struct heap_free_area *fa, *prev_fa;
void *end = (char *)mem + size;
HEAP_DEBUG (heap, "before __heap_free");
//找第一个结束地址内存块起始地址的FA
for (prev_fa = 0, fa = heap->free_areas; fa; prev_fa = fa, fa = fa->next)
if (unlikely (HEAP_FREE_AREA_END (fa) >= mem))
break;
if (fa && HEAP_FREE_AREA_START (fa) <= end)
{
//这里是相邻的情况
size_t fa_size = fa->size + size;
//下邻
if (HEAP_FREE_AREA_START (fa) == end)
if (prev_fa && mem == HEAP_FREE_AREA_END (prev_fa))
{
//上下都相邻的情况
fa_size += prev_fa->size;
__heap_link_free_area_after (heap, fa, prev_fa->prev);
}
}
else
/* FA is just before the new block, expand to encompass it. */
{
struct heap_free_area *next_fa = fa->next;
if (next_fa && end == HEAP_FREE_AREA_START (next_fa))
{
//上下相邻
fa_size += next_fa->size;
__heap_link_free_area_after (heap, next_fa, prev_fa);
fa = next_fa;
}
else
{
fa = (struct heap_free_area *)((char *)fa + size);
__heap_link_free_area (heap, fa, prev_fa, next_fa);
}
}
fa->size = fa_size;
}
else
/* Make the new block into a separate free-list entry. */
//没有找到FA。那说明是在堆的末端.或者与上下都不两邻,处在一个空洞中。调用//_heap_add_free_area将内存块链接进heap.这函数参考上面相关的分析
fa = __heap_add_free_area (heap, mem, size, prev_fa, fa);
HEAP_DEBUG (heap, "after __heap_free");
return fa;
}
这个函数的实现比较复杂。必须要耐着性子看
首先,先遍历heap中的FA。寻找第一个结束地起大于mem的空闲区.这里有几种情况。分别讨论如下:
1):找不到比mem大的空闲区,也就是说mem对应的内存区是在heap的末端。那就在mem对应的内存区末尾添入FA,然后加入到FA。它调用的是__heap_add_free_area()这函数我们在上面已经分析过了。如下图示:
2):找到了比mem大的空闲区fa,那也就是说,mem对应的内存是在heap的中间“空洞”中。这里有几种情况:
1:fa的起始地址要大于mem:这种情况跟第一种是一样的,只要新建一个FA插入即可。如下图示
2:mem的内存区与上下相邻的情况。如下所示:
因为有相邻的内存,所以要把合并到一个FA中