主分配区:
内存申请:可用通过mmap和brk获取系统内存。
数量:一个进程只能有一个主分配区
struct malloc_state:分配区结构体。
非主分配区:
内存申请:只能通过mmap获取系统内存。
内存申请libc_malloc():
1.获取分配区,如果发现没有可用分配区则创建新的分配区(heap_info)。 一个分配器只能被一个线程获取,并加锁,分配结束前,这个分配区不能被其他线程使用。大量线程分配内存,获取分配区时会频繁上锁。
2.(1)如果是主分配区,且分配内存大小小于M_MMAP_THRESHOLD,则去malloc_state->bins中查找已有的空闲内存,如果没有则通过brk申请内存。
(2)如果是主分配区,且分配内存大小大于M_MMAP_THRESHOLD,则通过mmap分配内存。
(3)如果是非主分配区,则无论申请内存多大,都通过mmap分配内存。
ptmalloc内存池(释放的内存没有归还系统,缓存起来):
1.fastbinsY[NFASTBINS]
_int_malloc 中实现逻辑.最先查找是否符合的缓存。
释放内存如果小于MAX_FAST_SIZE,会根据释放内存size找到在fastbinsY中对应下标。
申请内存时,如果申请内存大小在fastbinsY范围内存在,则从fastbinsY取出内存直接使用。
根据大小,查总fastbinsY中对应的位置
#define fastbin_index(sz) \
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
2.top
top chunk是heap的最高,当bins中没有找到适合的chunk就到top中找,如果top chunk比用户申请的大,分割后下面一部分分给用户, 上面的部分继续作为新的top chunk。
当和top相连的chunk 为free时, top则和其合并。如果相连的时fastbinsY中的内存,则不进行合并。
当top chunk大小不满足用户需求时,则通过brk申请内存,增加top chunk上的内存。
3.last_remainder
保存用户申请到chunk的size大于用户申请size的 剩余的chunk。
4.bins[NBINS*2-2]
bins分为三部分unsorted,small,large
unsorted: bins[1], 查找全部unsorted中的malloc_chunk,如果没有符合要求的,则从链表中摘除,放入small或者large中。最终全部的malloc_chunk将转移到small或者large中。
small:bins[2]-bins[63],每个下标对应的chunk链表大小2*8*index。可通过申请的size直接找到对应的chunk链表,或者不在链表中。
large:bins[64]-bins[127],都是大于1024字节的chunk。每个下标对应的chunk链表中大小可以不一样,但是根据从大到小排序。
根据大小,查找large中对应的位置
#define largebin_index_64(sz) \
(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)