堆基础---3 深入malloc的具体实现

本文详细解析了Linux中malloc的实现,包括heap_info、malloc_state、malloc_chunk等数据结构,以及ptmalloc初始化流程,涉及malloc_hook_ini、ptmalloc_init、__libc_malloc等多个关键函数的步骤,展示了内存分配的细节过程。
摘要由CSDN通过智能技术生成

感谢这篇文章 让我深入理解了malloc的具体实现

首先讲解几个数据结构

heap_info 通过循环链表串接

/* A heap is a single contiguous memory region holding (coalesceable)
   malloc_chunks.  It is allocated with mmap() and always starts at an
   address aligned to HEAP_MAX_SIZE.  */
typedef struct _heap_info
{
   
  mstate ar_ptr; /* Arena for this heap. */ //指向mstate结构 这个结构用以描述arena 不管是main还是thread arena 都只有一个mstate结构
  struct _heap_info *prev; /* Previous heap. */ //指向上一个heap_info结构 只对于thread_arena而言 可能存在多个heap 每个heap用一个heap_info结构加以表示
  size_t size;   /* Current size in bytes. */	 //heap_info结构的大小
  size_t mprotect_size; /* Size in bytes that has been mprotected 
                           PROT_READ|PROT_WRITE.  */
  /* Make sure the following data is properly aligned, particularly
     that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
     MALLOC_ALIGNMENT. */
  char pad[-6 * SIZE_SZ & MALLOC_ALIGN_MASK]; //用于对齐的 可以不用管
} heap_info;

malloc_state 即mstate 相当于代表一个arena的数据结构 通过单循环链表连接不同的arena

malloc_state 即mstate结构

struct malloc_state
{
   
  /* Serialize access.  */
  mutex_t mutex;
  /* Flags (formerly in max_fast).  */
  int flags;
  /* Set if the fastbin chunks contain recently inserted free blocks.  */
  /* Note this is a bool but not all targets support atomics on booleans.  */
  int have_fastchunks;
  /* Fastbins */
  mfastbinptr fastbinsY[NFASTBINS]; //存放fast bin的数组链表 这是个单链表结构
  /* Base of the topmost chunk -- not otherwise kept in a bin */
  mchunkptr top; //指向top chunk
  /* The remainder from the most recent split of a small request */
  mchunkptr last_remainder; //指向last remainder
  /* Normal bins packed as described above */
  mchunkptr bins[NBINS * 2 - 2]; //NBINS定义为128 由于在bins数组中的每个bin都有着一个fd和bk的指针 所以要乘2
  /* Bitmap of bins */
  unsigned int binmap[BINMAPSIZE]; //用于快速查找对应index的bin是否为空的一个位图
  /* Linked list */
  struct malloc_state *next; //指向下一个arena arena之间通过单循环链表构成的 所以只有一个next指针
  /* Linked list for free arenas.  Access to this field is serialized
     by free_list_lock in arena.c.  */
  struct malloc_state *next_free;
  /* Number of threads attached to this arena.  0 if the arena is on
     the free list.  Access to this field is serialized by
     free_list_lock in arena.c.  */
  INTERNAL_SIZE_T attached_threads;
  /* Memory allocated from the system in this arena.  */
  INTERNAL_SIZE_T system_mem;
  INTERNAL_SIZE_T max_system_mem;
};

malloc_chunk结构

struct malloc_chunk {
   
  INTERNAL_SIZE_T      mchunk_prev_size;  /* Size of previous chunk (if free).  */ //当上个块处于free状态的时候代表上个块的大小
  INTERNAL_SIZE_T      mchunk_size;       /* Size in bytes, including overhead. */	//size代表本chunk的大小 sizeof(currentChunk)
  struct malloc_chunk* fd;         /* double links -- used only if free. */ //仅用于free的块 fd和bk指针用于被bin所串连从而进行管理
  struct malloc_chunk* bk;
  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */ //这两个字段仅用于large freed chunk 即只在large freed chunk中出现 这两个域用于快速索引到下一个size的large chunk 
  struct malloc_chunk* bk_nextsize;
};

ptmalloc初始化流程

malloc_hook_ini初始化会走这个流程

static void * malloc_hook_ini (size_t sz, const void *caller){
   
    __malloc_hook = NULL;
    ptmalloc_init ();
    return __libc_malloc (sz);
}

首先将 _malloc_hook 这个全局变量设置为null,然后调用ptmalloc_init(),最后调用 __libc_malloc函数。

ptmalloc_init

该函数的实现在arena.c中

static void ptmalloc_init(void) {
   
    if (__malloc_initialized >= 0)
        return;
    __malloc_initialized = 0;
    tsd_key_create(&arena_key, NULL);
    tsd_setspecific(arena_key, (void *) &main_arena);
    thread_atfork(ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2);
    const char *s = NULL;
    if (__glibc_likely(_environ != NULL)) {
   
        char **runp = _environ;
        char *envline;
        while (__builtin_expect((envline = next_env_entry(&runp)) != NULL, 0)) {
   
            size_t len = strcspn(envline, "=");
            if (envline[len] != '=')
                continue;
            switch (len) {
   
            case 6:
                if (memcmp(envline, "CHECK_", 6) == 0)
                    s = &envline[7];
                break;
            case 8:
                if (!__builtin_expect(__libc_enable_secure, 0)) {
   
                    if (memcmp(envline, "TOP_PAD_", 8) == 0)
                        __libc_mallopt(M_TOP_PAD, atoi(&envline[9]));
                    else if (memcmp(envline, "PERTURB_", 8) == 0)
                        __libc_mallopt(M_PERTURB, atoi(&envline[9]));
                }
                break;
            case 9:
                if (!__builtin_expect(__libc_enable_secure, 0)) {
   
                    if (memcmp(envline, "MMAP_MAX_", 9) == 0)
                        __libc_mallopt(M_MMAP_MAX, atoi(&envline[10]));
                    else if (memcmp(envline, "ARENA_MAX", 9) == 0)
                        __libc_mallopt(M_ARENA_MAX, atoi(&envline[10]));
                }
                break;
            case 10:
                if (!__builtin_expect(__libc_enable_secure, 0)) {
   
                    if (memcmp(envline, "ARENA_TEST", 10) == 0)
                        __libc_mallopt(M_ARENA_TEST, atoi(&envline[11]));
                }
                break;
            case 15:
                if (!__builtin_expect(__libc_enable_secure, 0)) {
   
                    if (memcmp(envline, "TRIM_THRESHOLD_", 15) == 0)
                        __libc_mallopt(M_TRIM_THRESHOLD, atoi(&envline[16]));
                    else if (memcmp(envline, "MMAP_THRESHOLD_", 15) == 0)
                        __libc_mallopt(
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值