GLIBC内存池管理—分箱管理

1. GLIBC内存管理核心结构

1.1. malloc_chunk

struct malloc_chunk {
  INTERNAL_SIZE_T      mchunk_prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      mchunk_size;       /* Size in bytes, including overhead. */
  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
};

    struct malloc_chunk,该结构是GLIBC中内存管理的最小单元,每个用户分配的最小内存块必须为“2 * (user_size + offsetof(struct malloc_chunk, fd_nextsize))”,且与sizeof(size_t)的大小进行对齐。在32位机上size_t为4个字节,64位机上为8个字节。

1.2. malloc_state

struct malloc_state
{
  /* Serialize access.  */
  __libc_lock_define (, 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];

  /* Base of the topmost chunk -- not otherwise kept in a bin */
  mchunkptr top;

  /* The remainder from the most recent split of a small request */
  mchunkptr last_remainder;

  /* Normal bins packed as described above */
  mchunkptr bins[NBINS * 2 - 2];

  /* Bitmap of bins */
  unsigned int binmap[BINMAPSIZE];

  /* Linked list */
  struct malloc_state *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_state结构是GLIBC进行内存分箱管理的核心基础结构。

    在多线程环境中,为了提高内存管理效率,GLIBC对其提供了不同的管理策略,主要有:主线程管理和线程管理,即main_arena(该结构是一个全局静态变量,存放在内存数据段)和thread_arena(主要为线程提供内存管理机制)。这样GLIBC就会以main_arena为核心,将所有内存管理内存管理arena与main_arena进行管理起来(用一个双向链表进行管理)。

注:arena是malloc_state结构


1.3. 内存管理arena是否是无限增大?

    答案是否定的,arena的大小将会受到系统CPU核数的限制,一般为:核数 * sizeof(size_t)。


1.4. arena内存管理原理

    对进程内的每个arena必须保证其原子操作,这样就会对每个arena在进行内存分配和释放时进行加锁保护。在多线程环境中,内存分配策略为:当用户请求一块内存时,GLIBC首先会从main_arena开始,先获取该arena的锁,如果成功则基于该arena进行内存分配,否则继续向下个arena进行查找。如果所有arena查找完毕均不能满足用户请求的内存大小,则GLIBC将会利用chunk_top(下文介绍)来为用户分配内存。


2. arena内存分箱管理

    从malloc_state结构中可知,该结构包含fastbinsY,top,bins和binmap等核心结构。


2.1. fastbinsY

    fastbinsY字面意思就是快速箱子,在内存管理过程中除了tcache外,它的优先级最高。工作原理:在用户请求内存时,arena将会从其对应的fastbinsY中进行查找,看如果满足用户请求,则直接将其返回给用户使用。在fastbinsY中,其内存大小一般为128bytes(64位机中)。


2.2. bins

    bins是一个大小为128的大数组,并将其分为4类:bins[0]被称为unsorted bin;bins[2-63]被称为samll bin;bins[64-127]被称为large bin。

  • unsorted bin:顾名思义为无序箱子,其中盛放的内存块有大有小,且在arena机制中其优先级最低。
  • samll bin:小箱子,每个相邻箱子之间的内存大小相差8bytes(32位机)和16bytes(64位机)。
  • large bin:大箱子。

2.3. top

    在一个进程中,top扮演堆顶的角色,在Linux中堆是向上增长,即想要堆进行增长就必须通过sbrk系统调用增加top的大小。


3. GLIBC正真的内存池

    从上面基础知识介绍后 ,开始GLIBC内存池介绍。在GLIBC内存分箱管理前提下,每次用户请求malloc的内存块,经过free后并不是立马huan还给操作系统,而是直接缓存在arena中,如:fastbinsY、samll bin、large bin和unsorted bin(该顺序是按照分配和释放的优先级来排列)。

    malloc过程优先级:fastbinsY——>samll bin——>large bin——>unsorted bin——>top(最后一步为增长堆空间满足用户请求)

    free过程优先级:fastbinsY——>samll bin——>large bin——>unsorted bin——>top(释放堆空间)

    从上面的优先级顺序可知,从系统重新获取内存的优先级最低,这样可以减少系统调用造成的性能开销;将内存还给系统的优先级也是最低的,只有满足当前释放的内存大于或等于top所对应的内存大小(即:user_size >= top_chunk_size),在GLIBC中top chunk大小一般为128Kb。


4. GLIBC堆空间增加与减少

    在多线程主线程的堆空间主要通过sbrk系统调用进行扩展和缩减;而其他线程的堆空间主要通过mmap和munmap进行扩展和缩减。


4. malloc_trim

    通过调用malloc_trim(0),可以将GLIBC缓存的内存直接还给操作系统。malloc_trim函数是直接修改top chunk的大小,将所有arena中fastbinsY对应的chunk块与相邻空闲chunk块进行合并,然后一次性返还给系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值