分类:
2011-12-16 20:43:11
原文地址:Uclibc中的malloc机制分析(二) 作者:xgr180
三:堆空间的初始化:
全局变量__malloc_heap表示了整个堆栈空间。它的初始化过程如下示:
struct heap __malloc_heap = HEAP_INIT_WITH_FA (initial_fa);
HEAP_INIT_WITH_FA的定义如下:
#ifdef HEAP_USE_LOCKING
# define HEAP_INIT { 0, PTHREAD_MUTEX_INITIALIZER }
# define HEAP_INIT_WITH_FA(fa) { &fa._fa, PTHREAD_MUTEX_INITIALIZER }
#else
# define HEAP_INIT { 0 }
# define HEAP_INIT_WITH_FA(fa) { &fa._fa }
#endif
变量initial_fa初始化如下:
HEAP_DECLARE_STATIC_FREE_AREA (initial_fa, 256);
#define HEAP_DECLARE_STATIC_FREE_AREA(name, size) \
static struct \
{ \
char space[(size) - sizeof (struct heap_free_area)]; \
struct heap_free_area _fa; \
} name = { "", { (size), 0, 0 } }
如此可以看出初始化的堆空间为256个字节。从上面的初始化也可以看到,在FA结构的前面静态定义了一个数组空间。这也印证了上面说的“FA结构正好放在空闲区的后面”
四:FA结构的操作:
1:#define HEAP_FREE_AREA_SIZE(fa) ((fa)->size)
FA所代表的空闲区大小,此大小已经包含FA本身占的空间
2: #define HEAP_FREE_AREA_START(fa) ((void *)((char *)(fa + 1) - (fa)->size))
FA所代表空闲区的起始位置。fa+1到达空闲区末端。指针再下移大小个单位,即为空闲区的起始位置
3:#define HEAP_FREE_AREA_END(fa) ((void *)(fa + 1))
返回FA所表示空闲区的末尾。从FA所表示的结构可看出。从FA的地址上移一个FA的大小,刚好到达空闲的末尾
4:#define HEAP_MIN_FREE_AREA_SIZE \
HEAP_ADJUST_SIZE (sizeof (struct heap_free_area) + 32)
最少的空闲区大小。空闲区最少要能存上一个heap_free_area大小,此外还要有32字节的空闲,这是从效率来考虑的。Malloc分配内存的时候,有时候它会把一个FA分为两段。如果剩余的内存少于HEAP_MIN_FREE_AREA_SIZE.还不如全部都将内存分配出去。因为维护空闲内存需要影响效率。这从我们后面的malloc 与 free分析中可以看到
5: __heap_delete (struct heap *heap, struct heap_free_area *fa)
该函数是将fa从heap中删除,它的实现如下:
extern inline void
__heap_delete (struct heap *heap, struct heap_free_area *fa)
{
if (fa->next)
fa->next->prev = fa->prev;
if (fa->prev)
fa->prev->next = fa->next;
else
heap->free_areas = fa->next; //如果删除的是它的首节点
}
只是一个简单的链表操作,将fa从循环链表中脱节。
6: __heap_link_free_area (struct heap *heap, struct heap_free_area *fa,
struct heap_free_area *prev,
struct heap_free_area *next)
从代码注释上看该函数是指prev 与 next 之间的Fa合并到一起。实际上它只是在prev 与next之间插入了一项而已。
实现如下:
extern inline void
__heap_link_free_area (struct heap *heap, struct heap_free_area *fa,
struct heap_free_area *prev,
struct heap_free_area *next)
{
fa->next = next;
fa->prev = prev;
if (prev)
prev->next = fa;
else
heap->free_areas = fa; //插入节点为首节点的情况
if (next)
next->prev = fa;
}
7:__heap_link_free_area_after (struct heap *heap,
struct heap_free_area *fa,
struct heap_free_area *prev)
该函数实际上只是fa链接至prev后。等调用的时候再分析它。
__heap_link_free_area_after (struct heap *heap,
struct heap_free_area *fa,
struct heap_free_area *prev)
{
if (prev)
prev->next = fa;
else
heap->free_areas = fa;
fa->prev = prev;
}
8:__heap_add_free_area (struct heap *heap, void *mem, size_t size,
struct heap_free_area *prev,
struct heap_free_area *next)
该函数将从mem地址开始的size大小的内存所代码的FA结构,插入prev和next之间。它的实现如下:
extern inline struct heap_free_area *
__heap_add_free_area (struct heap *heap, void *mem, size_t size,
struct heap_free_area *prev,
struct heap_free_area *next)
{
//先取得内存段所在的FA结构,再将FA结构插入到prev与next之间
struct heap_free_area *fa = (struct heap_free_area *)
((char *)mem + size - sizeof (struct heap_free_area));
fa->size = size;
//将fa插入prev.next之间
__heap_link_free_area (heap, fa, prev, next);
return fa;
}
这函数的实现很有意思。它先取内存段的末地址,然后再返回heap_free_area个单位,存上一个FA结构。这里也印证了,FA结构刚好放在了空闲区的末尾