5.5 Ptmalloc初始化
Ptmalloc的初始化发生在进程的第一个内存分配请求,当 ptmalloc 的初始化一般都在用户的第一次调用 malloc() 或 remalloc() 之前,因为操作系统和 Glibc 库为进程的初始化做了不少工作,在用户分配内存以前, Glibc 已经分配了多次内存。
在 ptmalloc 中 malloc() 函数的实际接口函数为 public_mALLOc() ,这个函数最开始会执行如下的一段代码:
__malloc_ptr_t (*hook) (size_t, __const __malloc_ptr_t) = force_reg (__malloc_hook); if (__builtin_expect (hook != NULL, 0)) return (*hook)(bytes, RETURN_ADDRESS (0));
在定义了 __malloc_hook() 全局函数的情况下,只是执行 __malloc_hook() 函数,在进程初始化时 __malloc_hook 指向的函数为 malloc_hook_ini() 。
__malloc_ptr_t weak_variable (*__malloc_hook) (size_t __size, const __malloc_ptr_t) = malloc_hook_ini;
malloc_hook_ini() 函数定义在 hooks.c 中,实现代码如下:
static Void_t* #if __STD_C malloc_hook_ini(size_t sz, const __malloc_ptr_t caller) #else malloc_hook_ini(sz, caller) size_t sz; const __malloc_ptr_t caller; #endif { __malloc_hook = NULL; ptmalloc_init(); return public_mALLOc(sz); }
malloc_hook_ini() 函数处理很简单,就是调用 ptmalloc 的初始化函数 ptmalloc_init() ,然后再重新调用 pbulit_mALLOc() 函数分配内存。 Ptmalloc_init() 函数在初始化 ptmalloc 完成后,将全局变量 __malloc_initialized 设置为 1 ,当 pbulit_mALLOc() 函数再次执行时,先执行 malloc_hook_ini() 函数, malloc_hook_ini() 函数调用 ptmalloc_init() , ptmalloc_init() 函数首先判断 __malloc_initialized 是否为 1 ,如果是,则退出 ptmalloc_init() ,不再执行 ptmalloc 初始化。
5.5.1 Ptmalloc未初始化时分配/释放内存
当ptmalloc 的初始化函数 ptmalloc_init() 还没有调用之前, Glibc 中可能需要分配内存,比如线程私有实例的初始化需要分配内存,为了解决这一问题, ptmalloc 封装了内部的分配释放函数供在这种情况下使用。 Ptmalloc 提供了三个函数, malloc_starter() , memalign_starter() , free_starter() ,但没有提供 realloc_starter() 函数。这几个函数的实现如下:
static Void_t* #if __STD_C malloc_starter(size_t sz, const Void_t *caller) #else malloc_starter(sz, caller) size_t sz; const Void_t *caller; #endif { Void_t* victim; victim = _int_malloc(&main_arena, sz); return victim ? BOUNDED_N(victim, sz) : 0; } static Void_t* #if __STD_C memalign_starter(size_t align, size_t sz, const Void_t *caller) #else memalign_starter(align, sz, caller) size_t align, sz; const Void_t *caller; #endif { Void_t* victim; victim = _int_memalign(&main_arena, align, sz); return victim ? BOUNDED_N(victim, sz) : 0; } static void #if __STD_C free_starter(Void_t* mem, const Void_t *caller) #else free_starter(mem, caller) Void_t* mem; const Void_t *caller; #endif { mchunkptr p; if(!mem) return; p = mem2chunk(mem); #if HAVE_MMAP if (chunk_is_mmapped(p)) { munmap_chunk(p); return; } #endif #ifdef ATOMIC_FASTBINS _int_free(&main_arena, p, 1); #else _int_free(&main_arena, p); #endif }
这个函数的实现都很简单,只是调用 ptmalloc 的内部实现函数,这里就不详细介绍内部函数的实现了,在 5.7 和 5.8 节会详细介绍这些内部函数的实现细节。