前言:
最近刚学堆,特写此文巩固一下知识(水平有限,本文可能有错误,望读者留心)。
堆的结构:
在Linux中,堆是使用glibc的ptmalloc2的分配方式,而malloc本质上都是通过brk或mmap实现的。通过brk分配的堆其起始地址在数据段的结尾处,而通过mmap分配的堆起始地址则在数据段后的随机偏移处。
堆主要涉及到3种数据结构:
(1):heap_info,即Heap Header。因为一个thread可以包含多个heap,在当前heap不够用时,系统就会通过mmap分配新的的heap添加到thread arena中,为了便于管理,每个heap都会包含一个heap_info.
heap_info的数据结构:
typedef struct _heap_info { mstate ar_ptr; /* Arena for this heap. */ struct _heap_info *prev; /* Previous heap. */ size_t size; /* Current size in bytes. */ 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;
(2):malloc_state,即Arena Header,每个thread只有一个Arena Header,其包含bins,top chunk以及last remainder chunk等。
struct malloc_state { /* Serialize access. */ mutex_t mutex; /* Flags (formerly in max_fast). */ int flags; /* 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. */ struct malloc_state *next_free; /* Memory allocated from the system in this arena. */ INTERNAL_SIZE_T system_mem; INTERNAL_SIZE_T max_system_mem; };
(3):malloc_chunk,即Chunk Header,一个Heap被分为多个chunk,这个chunk的大小是由用户申请要分配的空间决定的(实际上chunk的可能大于用户申请分配的空间)
1 struct malloc_chunk { 2 /* #define INTERNAL_SIZE_T size_t */ 3 INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */ 4 INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */ 5 struct malloc_chunk* fd; /* double links -- used only if free. 这两个指针只在free chunk中存在*/ 6 struct malloc_chunk* bk; 7 /* Only used for large blocks: pointer to next larger size. */ 8 struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */ 9 struct malloc_chunk* bk_nextsize; 10 };
在glibc malloc中使用bin来管理空闲的chunk,其分为四类:fast bin,unsorted bin,small bin,large bin。
(一):fast bin
fast bin的个数只有10个,每一个fast bin都是由一个单链表构成。同一个链表中的所有chunk大小相同。默认情况下(以32位系统为例),每个bin之间按照步进8字节排列,即第一个bin的大小为8字节,第二个bin为16字节,以此类推。fast bin采用LIFO(后进先出)的原则,即最后进入链表的chunk会被最先分配。
fast bin在malloc_state中的结构为:
struct malloc_state { …… …… …… mfastbinptr fastbinsY[NFASTBINS]; //此为数组,用于存放10个fast bin …… …… …… };