Chinaunix首页 | 论坛 | 博客
  • 博客访问: 134469
  • 博文数量: 79
  • 博客积分: 30
  • 博客等级: 民兵
  • 技术积分: 435
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-16 19:55
文章分类
文章存档

2015年(1)

2013年(1)

2012年(9)

2011年(68)

我的朋友

分类:

2011-12-16 20:43:11

三:堆空间的初始化:

     全局变量__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)

该函数是将faheap中删除,它的实现如下:

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结构,插入prevnext之间。它的实现如下:

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结构插入到prevnext之间

  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结构刚好放在了空闲区的末尾

阅读(873) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~