glibc-malloc申请堆空间流程分析

malloc

最简单的一个申请堆空间:

void *malloc(size_t bytes) //分配所需的内存空间,并返回一个指向它的指针
  
//参数必须是2*SIZE_SZ的整数倍,如果不是系统会优化为整数倍
//32bit中SIZE_SE为4,也就是堆大小为8的倍数。
//64bit中SIZE_SZ为8,那么就是16的倍数。
  • 第一次调用malloc的时候会先初始化一个叫main_arena(libc中)的东西,并向kernel申请一大块内存区域(top tunck)作为堆
  • 再从这一大块内存区域分割出一个chunk,让malloc回传给程序(这个回传值是一个指针,这个指针指向这个chunk头,tcache前是指向presize,tcache后是指向tcache的数据体)。此时使用的这块内存叫chunk

源码角度:

  • 首先会进入到__libc_malloc(size_t bytes)函数
  • 然后会寻找合适的arena来分配内存
  • 如果没找到就来到 _int_malloc()函数分配内存

_int_malloc

  • 首先将用户请求的bytes(参数一)转换为chunk单位nb
  • 如果没有合适的arena则调用sysmalloc(),用mmap()分配chunk并返回,也就是区分是main线程还是子线程

mmap():为了更快的找到最合适的堆块搜索顺序为如下

fasg bin
small bin
unsorted bin
large bin
bins(是否有最小能满足的)
top chunk(切分chunk)

sysmalloc():当申请的大小(nb):

  • 大于mp_.mmap_threshold(128 * 1024 byte)时,通过mmap()函数分配
  • 小于时用brk()扩展内存形成新的top chunk,从而旧的 top chunk将被释放掉。从新的top chunk中切分nb大小的chunk给用户

free 释放堆空间

void free(void *mem)//指针指向一个要释放内存的chunk地址
//该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的
//如果传递的参数是一个空指针,则不会执行任何动作。

调用free函数释放指定堆空间时:

  1. 先进入到__libc_free()函数,将指向user data的指针转换为指向chunk的指针
  2. 如果是mmap()函数返回的chunk则通过munmap_chunk()函数释放
  3. 反之获取指向arena的指针,调用 _int_free()函数进行释放

_int_free

调用流程:

  1. 首先获得要释放chunk的大小
  2. 对其进行检查size是否过小或对齐
  3. 判断该chunk是否再fast bin范围内
  4. 如果是则插入fast bin -> 判断chunk是否由mmap()函数生成
  5. 如果不是则进行合并(先向后合并再前合并)
  6. 合并之后的chunk超过了FASTBIN_CONSOLIDATION_THRESHOLD则整理fast bin并返回给系统

释放内存流程如下:

fast chunk就直接进入fast bin先进后出,其他bin则先进入unsort bin充当缓存作用

当在之后申请内存时流程如下:(满足一个条件即退出流程)

小于fast bin大小时在fast bin中查找
大于fast bin后进入unsort bin查找合适大小free chunk
进行unsort bin遍历进行free chunk合并、归类在对应的bin区域查找
top chunk划分

划分)

%%--------------------------------------------------------------------

猜你喜欢

转载自blog.csdn.net/csdn546229768/article/details/129583431