ptmalloc代码浅析1

ptmalloc实现分析:
1. 在ptmalloc中,并没有定义malloc函数,而是定义了__libc_malloc(size_t nbytes);这样操作是为了不同平台。相应的free函数是__libc_free(void* mem);
2. __libc_malloc函数
void*
__libc_malloc(size_t bytes)
{
  mstate ar_ptr;  // 这个就是分配区的结构体描述,每个线程都会有一个分配区(如果它要分配动态内存的话)
  void *victim;  // 这个就是将要返回给user的实际虚拟内存地址
  // FIXME:以下这段函数不是特别明白。
  __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));


  arena_lookup(ar_ptr);  // 首先查看当前线程的线程存储中是否有分配区的指针(通常是之前分配过内存时保存过)
 // 下面宏判断ar_ptr是否!=0,如果是,则lock这个分配区,否则,获取或创建一个非主分配区,去lock它。
  arena_lock(ar_ptr, bytes); 
  if(!ar_ptr)  // 如果系统无法获取非主分配区,则分配内存失败
    return 0;
  victim = _int_malloc(ar_ptr, bytes); // 这个函数是关键函数,用来从分配区中获取虚拟内存(通常是chunk)
  if(!victim) {
    /* Maybe the failure is due to running out of mmapped areas. */
    if(ar_ptr != &main_arena) {  // 如果分配失败,而且分配区不是主分配区,可能mmap region内存不够了
      (void)mutex_unlock(&ar_ptr->mutex); // unlock当前分配区的锁
      ar_ptr = &main_arena;  // 切换到主分配区去申请内存
      (void)mutex_lock(&ar_ptr->mutex);  // 获取主分配区的锁
      victim = _int_malloc(ar_ptr, bytes);  // 然后从主分配区分配内存
      (void)mutex_unlock(&ar_ptr->mutex);  // 分配内存内存(不管是否成功),释放主分配区的锁
    } else {  // 第一次是从主分配区分配,但是失败了
      /* ... or sbrk() has failed and there is still a chance to mmap() */
      ar_ptr = arena_get2(ar_ptr->next ? ar_ptr : 0, bytes); // 尝试获取其它的非主分配区
      (void)mutex_unlock(&main_arena.mutex);  // 释放主分配区的锁
      if(ar_ptr) {  // 如果获取到了非主分配区
victim = _int_malloc(ar_ptr, bytes);  // 那么从这个非主分配区分配内存
(void)mutex_unlock(&ar_ptr->mutex);  // 然后释放这个分配区的锁
      }
    }
  } else  // 不管怎么样,我们都是要释放分配区的锁的。到这里,是第一次分配内存成功。
    (void)mutex_unlock(&ar_ptr->mutex);
// 简单的分配出来的内存:要么分配失败,要么是从mmap region分配出来的,
// 要么通过mem2chunk得到内存所属的chunk,进而得到chunk所被管辖的分配区
  assert(!victim || chunk_is_mmapped(mem2chunk(victim)) ||
ar_ptr == arena_for_chunk(mem2chunk(victim)));  
  return victim;
}

arena_lock宏定义如下:
# define arena_lock(ptr, size) do { \
  if(ptr) \
    (void)mutex_lock(&ptr->mutex); \
  else \
    ptr = arena_get2(ptr, (size)); \
} while(0)

#define heap_for_ptr(ptr) \
 ((heap_info *)((unsigned long)(ptr) & ~(HEAP_MAX_SIZE-1)))
#define arena_for_chunk(ptr) \
 (chunk_non_main_arena(ptr) ? heap_for_ptr(ptr)->ar_ptr : &main_arena)

// chunk的size域中倒数第2位(based on 0),存有分配区信息,要么是主分配区,要么是非主分配区。
#define chunk_non_main_arena(p) ((p)->size & NON_MAIN_ARENA)

本文通过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(
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值