TLSF算法原理概述
TLSF算法的核心优势在于其通过位运算执行内存块匹配算法,并兼顾了内存管理的额外内存消耗,无论是从内存池申请内存块还是释放内存块回内存池其操作都是O(1)。TLSF组织了一张一二级索引表映射其所有管理内存块的闲忙状态,并通过一个二维指针数组挂载所有空闲块双向链表的首节点。
一二级索引表中,一级索引通过一个无符号整形变量,变量所占字节由平台决定32位或64位,变量中每个bit映射一级内存块,内存块通过大小划分等级,等级组织上以2的指数幂划分,例如2^7 、2^8 、2^9 ...分别对应一级索引值7、8、9 ...,将内存块划分到128/256/512...内;这有一点需要注意的是一级索引值(FL)与一级索引等级(FLi),一级索引值指的是内存块对应的一级索引范围起始值的2的指数幂,例如一级索引值8对应的起始值28 =256,而一级索引等级对应的是一级索引无符号整形变量的bit index,通常会有一个一级索引偏移值,一级索引值减去一级索引偏移值得到一级索引等级,这个一级索引偏移值对应的就是一级索引表的起始等级,例如偏移值为7,表明一级索引值2^7 对应的就是第1级一级索引(等级从1开始),计算出的一级索引值减去偏移值7,即为一级索引等级,小于2^7 = 128字节的内存块都将挂载到一级范围内管理;设置一级偏移值目的是为了方便后面计算二级索引表以及挂载空闲块链表首节点的二维数组的下标,避免空间浪费。
一二级索引表中,二级索引表是一个无符号整形一维数组,进一步将内存块等级范围进行细分,其一维下标就是一级索引值,对应的就是该一级索引下各内存块进一步划分,划分方式为等分,划分依据是通过一个颗粒度变量决定通常取一个经验值,32位平台下通常为2^5 /2^4 即划分为32份,例如一级索引值为8时,一级索引范围为2^8 ~2^9 = 256 ~ 512之间,划分32份每份为256/32=8字节,二级进一步细分为32个8字节,各内存块根据大小放入对应的细分等级下管理。
二级链表头指针数组,挂载所有空闲块双向链表首节点的二维数组,是空闲内存块的管理实体,无论是申请还是释放,根据目标内存块的大小,计算出对应的一二级索引,对应的就是二维数组的下标,例如一二级索引fl,sl = [1, 2],对应的block[1][2]中存的就是272~280范围内的空闲块链表首节点。
申请内存块 tlsf_malloc(size),大致流程为:根据size计算目标空闲块所处一二级索引值,并转换成下标二级链表头指针数组的下标,取出目标内存块所在链表头节点,如果目标链表中还有空闲块,则直接取出首节点的空闲块即将该节点移出所处的空闲链表,如果目标链表中没有空闲块则向上一级继续寻找,二级索引链表没有就将一级索引也向上一级,如果都没有则分配失败;成功取出空闲块之后,需要判断空闲块是否大于size,如果大于足够的空间则需要对该空闲块进行切割,并将切割出的剩余空闲块重新插入空闲链表中。
释放内存块 tlsf_free(void * p),大致流程为:根据指针p向前偏移一个块头,得到内存块的块头即得到内存块的信息,将内存块数据域清除,并将其与其物理上的前一个空闲块合并(如果有这个空闲块),再将其与其物理上的后一个空闲块合并(如果有这个空闲块),将合并后的空闲块重新插入空闲链表。