当前位置:网站首页 > 技术博客 > 正文

动态内存申请的三个函数



1、申请内存池:

 
 

分析函数前先看几个结构体:

 


 

 


这么多结构体是否有些眼花缭乱,我们重点看下TLSF_struct和bhdr_struct,TLSF内存管理区的开头都会有一个TLSF_struct结构体,它存储了有关TLSF操作的相关信息,其中matrix[REAL_FLI][MAX_SLI]存储了所有分区的使用情况,fl_bitmap和sl_bitmap就是上面图分析的一级和二级索引,用位来标明是否是否有空闲块;

在TLSF中,内存块单位是由bhdr_struct来管理的,它内部结构体并不复杂,笔者已经对每个成员做了注释,相信不难理解,因为这里是以字方式对其,所以成员变量size的低2bit都为0,所以可以来代表其他含义;

了解了这些结构体,我们就可以着手分析函数了,这里关键是process_area函数,它负责将新的内存块分区:

 


 

这个函数实现并不复杂,它初始化了我们的之前申请的内存区域,我们先看下他的输入参数:

ib = process_area(GET_NEXT_BLOCK(mem_pool, ROUNDUP_SIZE(sizeof(tlsf_t))), ROUNDDOWN_SIZE(mem_pool_size - sizeof(tlsf_t)));

这里有两个入参,一个是mem_pool+sizeof(tlsf_t)地址,即我们TLSF申请的整个内存地址加上tlsf_struct所占用的地址,得到未使用内存的首地址,第二个参数是这块地址的大小,process_area函数的功能我通过下面的图进行说明,它初始化了mem_pool的内存区域;


 

如上图所示,process_area函数在mem_pool的开始定义了三块block,分别是ib,b,lb,上图对每一块的内存做了说明,尤其是size的最低2bit,我们在下面的函数中还会用到,还要注意process_area返回的是ib的地址;

回到init_memory_pool函数,接下来执行free_ex(b->ptr.buffer, tlsf);

 

 

上面代码第15行的b指向的地址就是上面图示中的内存块b的首地址,如果能看懂这点,就可以继续往下;

 

代码中两个if执行的条件,都不会执行;

if (tmp_b->size & FREE_BLOCK),这里的tmp_b其实是在上面process_area函数中的b内存块,b内存块的size赋值为USED_BLOCK,即为0,所以这里不会执行;

if (b->size & PREV_FREE) ,这里的b为process_area函数中的ib内存块,ib赋值为PREV_USED,即为0,所以这里也不会执行;

然后是函数MAPPING_INSERT(b->size & BLOCK_SIZE, &fl, &sl);这个函数是用我们之前介绍的利用大小计算两级f1和s1的值,源码已经给出,感兴趣的可以仔细研究,这里我们只需要知道MAPPING_INSERT函数用我们前面列出的公式,通过size得到了f1和s1;

INSERT_BLOCK(b, tlsf, fl, sl);是将b内存块插入内存块双向链表;

 

这里的while(0)是为了程序的健壮性,可自行百度,我们在pool_mem开头定义了tlsf_struct结构体,这个宏的主要作用就是将内存块b放到双向链表_tlsf -> matrix [_fl][_sl]中,插入时都是往表头插入;

这里想说明的一点是,这里是在初始化函数调用的INSERT_BLOCK宏,这里插入的位置是_fl=0,_sl=0,将上面内存图示的b块首地址赋给了_tlsf->matrix[0][0];

set_bit是置位操作,我们前面说过,如果为1,其对应位上的内存块就为空闲,当有使用时,需要调用clear_bit进行清零;

  到这里内存初始化函数就分析完了,我们得到了一大块可用内存,并且通过bitmap(两级索引)来管理内存块;

 

2、malloc:

 

看懂了前面的初始化函数,这个malloc函数就比较好理解了,可以分三步看这个函数:

step1.函数MAPPING_SEARCH(&size, &fl, &sl);它根据malloc入参size计算出fl和sl的值,公式之前已经给出;

step2.函数EXTRACT_BLOCK_HDR(b, tlsf, fl, sl);这个函数根据fl和sl的值提取出需要的内存,并给相对应的bitmap清零,标明这块内存已经使用;

step3.if...else部分,这部分是处理切割内存的,如果申请的内存区域可以被切割,就将其割为更小的块,并做相应处理;

malloc函数还是比较简单的,这里不做赘述了;

3、free函数

我们在init函数中,其实已经分析了free函数;

好的,到这里我们已经将TLSF的主要思路介绍明白了,TLSF其实还要负责的多,代码中有许多优化处理,包括公式与c代码的转换;比如ffs和fls,分别表示find first set(返回最低位为1的位置)和find last set(返回最高位为1的位置),ffs可以在c中找到刚好大于size(申请大小)的内存块位置;fls可以用来计算下面函数:

其他细节可以下载TLSF代码学习,稍后笔者会把1.0-3.0三个版本代码都上传上去,希望大家多多支持;

  • 上一篇: 组策略教程
  • 下一篇: 动态规划01背包算法
  • 版权声明


    相关文章:

  • 组策略教程2024-11-23 08:30:04
  • java的网络编程有什么用2024-11-23 08:30:04
  • debian镜像下载2024-11-23 08:30:04
  • 进程的pid是固定的吗2024-11-23 08:30:04
  • 小程序添加测试人员2024-11-23 08:30:04
  • 动态规划01背包算法2024-11-23 08:30:04
  • sql orm框架2024-11-23 08:30:04
  • storm flink区别2024-11-23 08:30:04
  • kvm虚拟化技术的实现方式2024-11-23 08:30:04
  • 正品蓝导航—最全收入2024-11-23 08:30:04