Glibc内存管理--ptmalloc2源代码分析(十八)

5.5 Ptmalloc初始化

 

Ptmalloc的初始化发生在进程的第一个内存分配请求,当 ptmalloc 的初始化一般都在用户的第一次调用 malloc()remalloc() 之前,因为操作系统和 Glibc 库为进程的初始化做了不少工作,在用户分配内存以前, Glibc 已经分配了多次内存。

ptmallocmalloc() 函数的实际接口函数为 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.75.8 节会详细介绍这些内部函数的实现细节。

 

 

 

本文通过Glibc的内存暴增问题,主要介绍了系统的内存管理问题,具体如下: 目录 1. 问题 2. 基础知识 2.1 X86平台Linux进程内存布局 2.1.1 32位模式下进程内存经典布局 2.1.2 32位模式下进程默认内存布局 2.1.3 64位模式下进程内存布局 2.2 操作系统内存分配的相关函数 2.2.1 Heap操作相关函数 2.2.2 Mmap映射区域操作相关函数 3. 概述 3.1 内存管理一般性描述 3.1.1 内存管理的方法 3.1.2 内存管理器的设计目标 3.1.3 常见C内存管理程序 3.2 Ptmalloc内存管理概述 3.2.1 简介 3.2.2 内存管理的设计假设 3.2.3 内存管理数据结构概述 3.2.4 内存分配概述 3.2.5 内存回收概述 3.2.6 配置选项概述 3.2.7 使用注意事项 4. 问题分析及解决 5. 源代码分析 5.1 边界标记法 5.2 分箱式内存管理 5.2.1 Small bins 5.2.2 Large bins 5.2.3 Unsorted bin 5.2.4 Fast bins 5.3 核心结构体分析 5.3.1 malloc_state 5.3.2 Malloc_par 5.3.3 分配区的初始化 5.4 配置选项 5.5 Ptmalloc的初始化 5.5.1 Ptmalloc未初始化时分配/释放内存 5.5.2 ptmalloc_init()函数 5.5.3 ptmalloc_lock_all(),ptmalloc_unlock_all(),ptmalloc_unlock_all2() 5.6 多分配区支持 5.6.1 Heap_info 5.6.2 获取分配区 5.6.3 Arena_get2() 5.6.4 _int_new_arena() 5.6.5 New_heap() 5.6.6 get_free_list()和reused_arena() 5.6.7 grow_heap(),shrink_heap(),delete_heap(),heap_trim() 5.7 内存分配malloc 5.7.1 public_mALLOc() 5.7.2 _int_malloc() 5.8 内存释放free 5.8.1 Public_fREe() 5.8.2 _int_free() 5.8.3 sYSTRIm()和munmap_chunk(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值