fast bins、unsorted bins、malloc state
FastBins
大小在(64位平台)0x20~0x80之间,当chunk的大小在fastbin之间的时候,当释放时,会直接放入fastbin中。
fastbin是用fd来进行遍历的,所遵循的数据结构是后进先出(fd代表下一个chunk的地址)
malloc
如果申请的 chunk 的大小位于 fastbin 范围内,需要注意的是这里比较的是无符号整数。此外,是从 fastbin 的头结点开始取 chunk。
1 /* 2 If the size qualifies as a fastbin, first check corresponding bin. 3 This code is safe to execute even if av is not yet initialized, so we 4 can try it without checking, which saves some time on this fast path. 5 */ 6 7 if ((unsigned long) (nb) <= (unsigned long) (get_max_fast())) { 8 // 得到对应的fastbin的下标 9 idx = fastbin_index(nb); 10 // 得到对应的fastbin的头指针 11 mfastbinptr *fb = &fastbin(av, idx); 12 mchunkptr pp = *fb; 13 // 利用fd遍历对应的bin内是否有空闲的chunk块, 14 do { 15 victim = pp; 16 if (victim == NULL) break; 17 } while ((pp = catomic_compare_and_exchange_val_acq(fb, victim->fd, 18 victim)) != victim); 19 // 存在可以利用的chunk 20 if (victim != 0) { 21 // 检查取到的 chunk 大小是否与相应的 fastbin 索引一致。 22 // 根据取得的 victim ,利用 chunksize 计算其大小。 23 // 利用fastbin_index 计算 chunk 的索引。 24 if (__builtin_expect(fastbin_index(chunksize(victim)) != idx, 0)) { 25 errstr = "malloc(): memory corruption (fast)"; 26 errout: 27 malloc_printerr(check_action, errstr, chunk2mem(victim), av); 28 return NULL; 29 } 30 // 细致的检查。。只有在 DEBUG 的时候有用 31 check_remalloced_chunk(av, victim, nb); 32 // 将获取的到chunk转换为mem模式 33 void *p = chunk2mem(victim); 34 // 如果设置了perturb_type, 则将获取到的chunk初始化为 perturb_type ^ 0xff 35 alloc_perturb(p, bytes); 36 return p; 37 } 38 }
unsorted bins
unsorted bin是small bin和large bin的一个cache,small bin在释放的时候,会先放入unsorted bin中,在unsorted中没有适合块时,unsorted bin会把chunk放入其所属的bin中,然后在适合的bin中分配chunk,如果还没有适合的chunk,就会进行chunk的合并,合并之后,若还没有相应的chunk,就会向top chunk来申请内存。Bins 数组中的元素 bin[1]用于存储 unsorted bin 的 chunk 链表头。
如果在分配unsorted bins时,但有合适的块,但比需要的块要大,就会进行切割,切割后,剩余的chunk依旧会在unsorted bin中
malloc state
每个分配区是 struct malloc_state 的一个实例,ptmalloc 使用 malloc_state 来管理分配区,而参数管理使用 struct malloc_par,全局拥有一个唯一的 malloc_par 实例。
struct malloc_state { /* Serialize access. */ mutex_t mutex; /* Flags (formerly in max_fast). */ int flags; #if THREAD_STATS /* Statistics for locking. Only used if THREAD_STATS is defined. */ long stat_lock_direct, stat_lock_loop, stat_lock_wait; #endif /* 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; #ifdef PER_THREAD /* Linked list for free arenas. */ struct malloc_state *next_free; #endif /* Memory allocated from the system in this arena. */ INTERNAL_SIZE_T system_mem; INTERNAL_SIZE_T max_system_mem; };
Mutex:用于串行化访问分配区,当有多个线程访问同一个分配区时,第一个获得这个 mutex 的线程将使用该分配区分配内存,分配完成后,释放该分配区的 mutex,以便其它线程使用该分配区。
Flags:记录了分配区的一些标志,bit0 用于标识分配区是否包含至少一个 fast bin chunk,bit1 用于标识分配区是否能返回连续的虚拟地址空间。
fastbinsY:拥有 10(NFASTBINS)个元素的数组,用于存放每个 fast chunk 链表头指针,所以 fast bins 最多包含 10 个 fast chunk 的单向链表。
top:一个 chunk 指针,指向分配区的 top chunk。
last_remainder:是一个 chunk 指针,分配区上次分配 small chunk 时,从一个 chunk 中分裂出一个 small chunk 返回给用户,分裂后的剩余部分形成一个 chunk,last_remainder 就是指向的这个 chunk。
binmap:一个 int 数组,ptmalloc 用一个 bit 来标识该 bit 对应的 bin 中是否包含空闲 chunk。