堆入门2—chunk结构

Chunk

Chunk是Ptmalloc最基本的内存单位,这块内存在 ptmalloc 内部用 malloc_chunk 结构管理chunk。当程序申请的 chunk 被 free 后,会被加入到相应的空闲管理列表中。

chunk 有使用和空闲(释放)两种状态,其内部结构不同。

chunk结构

/*
  This struct declaration is misleading (but accurate and necessary).
  It declares a "view" into memory allowing access to necessary
  fields at known offsets from a given base. See explanation below.
*/
struct malloc_chunk {
  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */
  struct malloc_chunk* fd;         /* double links -- used only if free. */
  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. */
  struct malloc_chunk* bk_nextsize;
};

其字段具体解释:
prev_size

  • 如果本 chunk 前面一个 chunk 处于释放状态,那么 prev_size 成员才有用,此时用来记录前一个 chunk 的大小。
  • 如果本 chunk 前面一个 chunk 处于使用状态,那么 prev_size 成员为 0 是没有用的;但是当前一个 chunk 申请的大小大于前一个 chunk 的大小时,那么该字段可以用来给前一个 chunk 使用这就是 chunk 的空间复用

size

  • 该 chunk 的大小,大小必须是 2 SIZE_SZ 的整数倍。如果申请的内存大小不是 2 SIZE_SZ 的整数倍,会被转换满足大小的最小的 2 * SIZE_SZ 的倍数。32 位系统中,SIZE_SZ 是 4 字节;64 位系统中,SIZE_SZ 是 8 字节。

fd 、bk

  • chunk 处于使用状态时,从 fd 字段开始是用户的数据,fd 和 bk都不存在。
  • chunk 释放状态时,会被添加到对应的空闲管理链表中,其字段的含义如下
  • fd 指向上一个 free 的 chunk 的 prev_size
  • bk 指向下一个 free 的 chunk 的 prev_size
    通过 fd 和 bk 可以将空闲的 chunk 块加入到相应的链表进行统一管理
    file

fd_nextsize、bk_nextsize

  • 也是只有chunk空闲的时候才使用,不过其用于较大的chunk(large chunk):
  • fd_nextsize:指向前一个与当前 chunk 大小不同的第一个空闲块,不包含bin的头指针。
  • bk_nextsize:指向后一个与当前 chunk 大小不同的第一个空闲块,不包含 bin 的头指针。
  • 一般空闲的 large chunk 在 fd 的遍历顺序中,按照由大到小排列。便于寻找合适 chunk 。

size 低3位

Chunk的对齐:32位 SIZE_SZ 为8字节;64位 SIZE_SZ 为16字节
Chunk的最小尺寸:32位为16字节;64位为24/32字节

8字节对齐就导致了size的低3位固定位0,然后为了充分利用内存空间,这低三位的储存了其他信息:

分别是 PREV_INUSE;IS_MMAPPED;NON_MAIN_ARENA

  • NON_MAIN_ARENA: 记录chunk是否属于不主线程,若为1则不属于,0则属于。

  • IS_MMAPPED: 1 表示使用mmap映射区域,0为使用heap区域。

  • PREV_INUSE: 为1时表示上一个chunk在使用中,0表示上一个chunk已经释放

堆管理器可以通过这些信息找到前一个被释放的chunk的位置。

Chunk有3种形式:
· Allocated chunk
· Free chunk
· Top chunk
· Last remainder chunk

常说的chunk一般也就按使用情况分为
allocated chunk:当前chunk是被应用层用户所使用的。
free chunk:当前chunk是空闲的,没有被应用层用户所使用。

下面部分需要先了解bin机制

Top Chunk:

  • 概念:当一个chunk处于一个arena的最顶部(即最高内存地址处)的时候,就称之为 top chunk 即初始化后从未分配的 chunk 。
  • 作用:该chunk并不属于任何bin,而是在系统当前的所有free chunk(无论那种bin)都无法满足用户请求的内存大小的时候,将此chunk 分配给用户使用。
  • 分配的规则:如果top chunk的大小比用户请求的大小要大的话,就将该top chunk分作两部分:(1)用户请求的chunk;(2)剩余的部分成为新的top chunk。否则,就需要扩展heap或分配新的heap了——在main arena中通过sbrk扩展heap,而在thread arena中通过mmap分配新的heap。

Last Remainder Chunk:

  • 它是怎么产生的:当用户请求的是一个small chunk,且该请求无法被small bin、unsorted bin满足的时候,就通过binmaps遍历bin查找最合适的chunk,如果该chunk有剩余部分的话,就将该剩余部分变成一个新的chunk加入到unsorted bin中,另外,再将该新的chunk变成新的last remainder chunk。

  • 它的作用是什么:此类型的chunk用于提高连续malloc(small chunk)的效率,主要是提高内存分配的局部性。那么具体是怎么提高局部性的呢?举例说明。当用户请求一个small chunk,且该请求无法被small bin满足,那么就转而交由unsorted bin处理。同时,假设当前unsorted bin中只有一个chunk的话——就是last remainder chunk,那么就将该chunk分成两部分:前者分配给用户,剩下的部分放到unsorted bin中,并成为新的last remainder chunk。这样就保证了连续malloc(small chunk)中,各个small chunk在内存分布中是相邻的,即提高了内存分配的局部性。

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据