LiteOS内存管理:TLSF算法

问题背景

TLSF算法主要是面向实时操作系统提出的,对于RTOS而言,执行时间的确定性是最根本的,然而传统的动态内存分配器(DMA,Dynamic Memory Allocator)存在两个主要问题:

  1. 最坏情况执行时间不确定(not bounded)或者复杂度过高。
  2. 碎片化问题。

TLSF的提出,较好地解决了以上两个问题:将动态内存的分配与回收时间复杂度都降到了O(1)时间复杂度,并且采用了Good-fit的分配策略保证系统运行时不会产生过多碎片。

TLSF概要

TLSF(Two-Level Segregated Fit),从命名来看主要分为三部分:

  1. Segregated Free List
  2. Two-Level Bitmap
  3. Good Fit

前两个是数据结构,第三个是分配策略。
TLSF主要采用两级位图(Two-Level Bitmap)与分级空闲块链表(Segregated Free List)的数据结构管理动态内存池(memory pool)以及其中的空闲块(free blocks),用Good-Fit的策略进行分配。

隔离空闲链表

将Segregated Free List拆开,分为:

  1. List:隐式链表,管理所有内存块。
  2. Free List:显示链表,只管理空闲块。
  3. Segregated Free List:隔离空闲块链表,按空闲块大小分级,用多个链表管理。

List

链表是内存管理中最常见的数据结构,在一块内存块头部添加一个头结点,记录该Block本身的信息,以及前后级Block的关系。

隐式链表,链接所有内存块,只记录内存块大小,由于内存块相连,通过头结点指针加内存块大小即可得到下一个内存块的位置。
没有显示指明内存块的地址,而是通过计算得到,所以又叫做隐式链表。

当需要分配内存时,需要从第一块内存块开始检索,检查该内存块是否被分配以及内存块大小是否满足需要,直到找到大小合适的空闲块分配出去。

隐式链表主要问题在于当内存分配时并不需要检索已分配的内存块,这浪费了不少时间,只需要检索空闲块即可。

因此,显示空闲块链表在空闲块头部添加一个指针域,指向下一个空闲块,这样检索时会跳过已分配的内存块(used blocks)。


Segregated Free List

隐式链表和显示链表主要问题在于当空闲块个数为n时,检索复杂度在O(n)级别,速度较慢,分级空闲块链表优化了空闲块检索的复杂度,粗略计算大概降到O(log n)级别。

分级空闲块链表(Segregated Free List)的设计思想是将空闲块按照大小分级,形成了不同块大小范围的分级(class),组内空闲块用链表链接起来。

每次分配时先按分级大小范围查找到相应链表,再从相应链表挨个检索合适的空闲块,如果找不到,就在大小范围更大的一级查找,直到找到合适的块分配出去。

Two-Level Bitmap

上面我们介绍了分级空闲块链表的原理,但是我们并没有提及如何按照空闲块大小分级。

TLSF算法引入了位图(bitmap)来解决这个问题。

位图(Bitmap)

  1. 节省存储空间:用1-bit表示某个区间范围大小的空闲块是否存在。
  2. 位操作速度快:部分体系结构有加速特殊位操作的指令(如clz,ffs,fls)。

SEgregated List + Two-Level Bitmap

TLSF采用了两级位图(Two-Level Bitmap)来管理不同大小范围的空闲块链(free block lists)。上图中包含三个虚线矩形框分别是:

  1. 第一级位图,表示内存块的粗粒度范围,一般是2的幂次粒度。
  2. 第二级位图,表示内存块的细粒度范围。
  3. 第三个框是内存中真正的空闲内存块(free blocks)。

内存分配与释放流程(简版)

有了TLSF的大体框架概念以后,就可以先看一下内存alloc与free的简要流程。

内存分配流程

  1. 在位图中搜索合适的空闲块大小范围,找到free list的头指针。
  2. 基于free list的头指针检索list分配空闲块。

内存释放流程

  1. 将需要释放的内存块置为空闲块。
  2. 与该空闲块物理上相邻的空闲块合并。
  3. 计算合并后的空闲块大小范围,检索位图找到对应的free list。
  4. 将该内存块加入free list,返回给内存池。

Good-fit

常规思路:Best-fit(内部碎片最优)

常规思路是:找到能满足内存请求大小的最小空闲块,就会有下面的流程(以搜索大小为69字节的空闲块为例)。

  1. 基于位运算找到请求大小所在的第一级位图(First-Level bitmap)对应的粗粒度范围([ 64 ~ 128 ]),也就是二级位图的索引
  2. 在粗粒度范围内,根据二级位图索引检索第二级位图(Second-Level bitmap)得到细粒度范围([ 68 ~ 70 ])
  3. 如上图所示,沿着右下角空闲块链表可以检索到69字节的那一块是Best-fit

Best-fit已经很不错了,但仍然有提升空间。Best-fit策略最主要的问题还在于第三步,仍然需要检索对应范围的那一条空闲块链表,存在潜在的时间复杂度。

Good-fit(少量碎片换取O(1)时间复杂度)

Good-fit并不保证找到满足需求的最小空闲块,而是尽可能接近要分配的大小。

还以上述搜索大小为69字节的空闲块为例,查找范围稍微大一点儿的,如[70,72],这样设计的好处是[70,72]对应的空闲块链中每一块都能满足需求,不需要检索空闲块链表找到最小的,而是直接取空闲块链中第一块即可。整体上也不会造成太多碎片。

相关推荐
wniuniu_20 分钟前
socc19 echash部分代码讲解 二 hashtable
算法·哈希算法
ai.Neo1 小时前
牛客网NC276055:三根木棒能否组成三角形问题详解(ACM中的A题)
数据结构·c++·算法
じ☆ve 清风°1 小时前
滑动窗口算法详解与C++实现
开发语言·c++·算法
东莞呵呵2 小时前
吴恩达机器学习(1)——机器学习算法分类
算法·机器学习·分类
远瞻。6 小时前
【论文阅读】人脸修复(face restoration ) 不同先验代表算法整理2
论文阅读·算法
先做个垃圾出来………9 小时前
哈夫曼树(Huffman Tree)
数据结构·算法
phoenix@Capricornus10 小时前
反向传播算法——矩阵形式递推公式——ReLU传递函数
算法·机器学习·矩阵
Inverse16211 小时前
C语言_动态内存管理
c语言·数据结构·算法
数据与人工智能律师11 小时前
虚拟主播肖像权保护,数字时代的法律博弈
大数据·网络·人工智能·算法·区块链
wuqingshun31415911 小时前
蓝桥杯 16. 外卖店优先级
c++·算法·职场和发展·蓝桥杯·深度优先