堆几种常见的数据结构
- _heap_info
- malloc_state
- malloc_chunk
- _heap_info (用于管理heap的数据结构)
typedef struct _heap_info{
mstate ar_ptr;/*这个heap所在的arena*/
struct _heap_info *prev;/*上一个heap*/
size_t size;/*当前大小*/
size_t mprotect_size;/*size in bytes that has been mprotected PROT_READ|PROT_WRITE*/
char pad[-6 * SIZE_SZ & MALLOC_ALIGN_MASK];/*用于对齐*/
}heap_info
- malloc_state(arena的数据结构)
struct malloc_state{
mutex_t mutex;/*同步访问相关,互斥锁*/
int flags;/*标志位,用来表示当前arena的特征,比如是否有fast bin的存在,内存是否连续等*/
mfastbinptr fastbins[NFASTBINS];/*fastbins*/
mchunkptr top;/*top chunk,未被分配的,在堆顶的部分*/
mchunkptr last_remainder;/*最后一次拆分top chunk得的剩余内容*/
mchunkptr bin[BINS*2];/*bins 一个free chunk的链表数组*/
unsigned int binmap[BINMAPSIZE];/*bins的一个位图,用于表明bins是否为空*/
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
};
mfastbinptr 的定义:typedef struct malloc_chunk *mfastbinptr;
mchunkptr 的定义:typedef struct malloc_chunk *mchunkptr;
- malloc_chunk(chunk的数据结构)
struct malloc_chunk{
INTERNAL_SIZE_T prev_size;
/*如果前一个的chunk状态是free的话,这个就是前一个chunk的大小,低地址的chunk*/
INTERNAL_SIZE_T size;/*本堆块的长度=size字段长度+用户申请长度+对齐*/
struct malloc_chunk* fd;/*当chunk是空闲时使用,用作双向链表 ,指向下一个空闲的chunk*/
struct malloc_chunk* bk;/*指向上一个空闲的chunk,先进的chunk*/
/*bin中先进的为last,后进的为next*/
struct malloc_chunk* fd_nextsize;/*当chunk空闲的时候才使用,用于largebin*/
struct malloc_chunk* bk_nextsize; /*用于指向后一个与当前大小不相同的空闲块*/
};
与malloc_chunk的一些知识点:
- prev_size:如果该 chunk 的物理相邻的前一地址chunk(两个指针的地址差值为前一chunk大小)是空闲的话,那该字段记录的是前一个 chunk 的大小(包括 chunk 头)。否则,该字段可以用来存储物理相邻的前一个chunk 的数据。这里的前一 chunk 指的是较低地址的 chunk 。
- size :该 chunk 的大小,大小必须是 2 * SIZE_SZ 的整数倍。如果申请的内存大小不是 2 * SIZE_SZ 的整数倍,会被转换满足大小的最小的 2 * SIZE_SZ 的倍数。32 位系统中,SIZE_SZ 是 4;64 位系统中,SIZE_SZ 是 8。 该字段的低三个比特位对 chunk 的大小没有影响,用作标志位,从高到低依次表示 N M P
- N 是 NON_MAIN_ARENA ,表示该chunk是否属于主线程 0表示属于,1表示不属于。
- M 是 IS_MAPPED,表示该chunk是否由mmap分配
- P 是 PREV_INUSE,记录前一个chunk始够被分配,分配的话设为1,未被分配的话就设为0
- fd_nextsize和 bk_nextsize:也是只有当 chunk 空闲的时候才使用,用于large chunk