📜  二次幂的自由列表分配器|核心记忆分配器

📅  最后修改于: 2021-08-29 11:07:41             🧑  作者: Mango

两个空闲列表的功效是一种用于内核内存分配的算法。它经常用于在用户级C库中实现malloc()free()。这种方法使用了一组空闲列表。每个列表存储特定大小的缓冲区,所有大小均为2的幂。例如,考虑下图有六个自由列表,存储尺寸32,64,128,256,512,以及1024个字节的缓冲器。

每个缓冲区具有固定大小的标头,这导致可用区域减少。当缓冲区空闲时,其头存储指向下一个空闲缓冲区的指针。分配缓冲区后,其标题指向应将其返回到的空闲列表。在一些实现中,它包含分配的区域的大小。这有助于检测某些错误,但需要free()例程才能根据大小计算空闲列表的位置。

当客户端调用malloc()时,传递所需的大小作为参数。分配器计算最小缓冲区的大小,该大小足以满足请求。这涉及将标头( 4个字节)的空间增加到请求的大小,并将结果值舍入到下一个2的幂。 32字节的缓冲区满足0-28字节的请求, 64字节的缓冲区满足29-60字节的请求,依此类推。然后,分配器从适当的空闲列表中删除缓冲区,并且标头中的指针指向相应的空闲列表。它向调用方返回指向缓冲区后标头后立即字节的指针。
下图表示分配的缓冲区和指向缓冲区的指针的概念图。

当客户端释放缓冲区时,它将调用free()例程,并将malloc()返回的指针作为参数传递。用户不必指定要释放的缓冲区的大小。但是,必须释放从malloc()获得的整个缓冲区;没有提供仅释放分配的缓冲区的一部分的规定。 free()方法将指针移回四个字节以访问标头。它从头接收空闲列表指针,并将缓冲区放在该列表上。

分配器可以通过以下三种方式之一处理针对该大小的新malloc()请求:

  • 阻塞请求,直到释放适当大小的缓冲区为止。
  • 用更大的缓冲区满足请求,从下一个列表开始,继续搜索直到找到一个非空列表。
  • 从页面级分配器获取更多内存,以生成更多该大小的缓冲区。

优点

  • 该算法简单且相当快。
  • 该算法的主要目标是避免资源图方法的冗长的线性搜索并完全消除碎片问题。
  • 分配器还提供了一个熟悉的编程接口,其重要优点是不需要为free()例程提供缓冲区大小作为参数。结果,可以将已分配的缓冲区传递给其他功能和子系统,并最终仅使用指向缓冲区的指针来释放它。
  • 该接口不允许客户端仅释放分配的缓冲区的一部分。

缺点

  • 将请求四舍五入为2的下一个幂通常会在缓冲区中留下大量未使用的空间,从而导致较差的内存利用率。
  • 由于必须将头存储在分配的缓冲区中,因此问题变得更加严重。例如,一个512字节的请求将占用一个1024字节的缓冲区。
  • 没有提供合并相邻的空闲缓冲区来满足更大要求的措施。通常,每个缓冲区的大小在其生命周期内保持不变。唯一的灵活性是,有时可能会将大型缓冲区用于小型请求。
  • 尽管某些实现允许分配器从分页系统中窃取内存,但没有提供将多余的空闲缓冲区返回给页面级分配器的措施。