You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于固定主存数组的伙伴内存分配器:空闲块查找机制咨询

伙伴内存分配器:空闲块查找全解析

嘿,我来帮你把伙伴系统查找空闲块的逻辑掰扯清楚——毕竟你是要在固定数组上实现,得把细节落地才行。

首先得明确伙伴系统的核心前提:所有内存块都是2的幂次大小,而且空闲块是按「大小分类」管理的(比如用不同的空闲链表,每个链表对应一种2的幂次大小)。因为你不能用new,所以这些链表得依托数组本身来实现——比如每个空闲块的头部用数组里的几个位置存元数据:块大小、是否空闲、伙伴块的数组下标、链表前驱/后继的数组下标。

下面是具体的查找步骤:

1. 确定所需的最小块大小

当你需要分配k字节的内存时,首先计算出最小的2的幂次值2^m,使得2^m >= k。比如要分配5字节,那2^3=8就是你要找的块大小——伙伴系统从不分配非2幂次的块。

2. 从对应大小的空闲链表开始查找

直接去对应2^m大小的空闲链表中检查:

  • 如果链表不为空,直接取出第一个空闲块(或者任意一个,看你实现的链表策略),标记为已分配,然后从链表中移除它,分配完成。
  • 如果这个大小的链表是空的,就需要往更大的块级别找,进入下一步的拆分流程。

3. 向上查找更大的空闲块并拆分

从2^(m+1)大小的链表开始,依次检查更大的块(2^(m+2)、2^(m+3)…直到最大的块大小,也就是整个数组的大小):

  • 一旦找到某个大小2^p(p > m)的空闲块,就把这个块拆分成两个相等的伙伴块,每个块的大小是2^(p-1)。
  • 拆分的时候,要在数组中给这两个块分别设置元数据:标记它们的大小为2^(p-1),记录彼此的伙伴下标(比如第一个块的伙伴是它的起始下标+2^(p-1),第二个块的伙伴是起始下标)。
  • 把其中一个拆分后的块(大小2^(p-1))放回对应的空闲链表;如果p-1还大于m,就重复这个拆分过程,直到拆分出大小为2^m的块,然后把这个块分配出去,另一个伙伴块加入2^m的空闲链表。

举个实际例子(假设你的数组大小是16字节,即2^4):

  • 初始状态:整个数组是一个大小16的空闲块,在16字节的空闲链表中。
  • 现在要分配5字节,需要8字节的块:检查8字节链表为空,于是去16字节链表取块。
  • 把16字节块拆分成两个8字节块(起始下标0-7和8-15),标记它们的伙伴关系,把其中一个(比如0-7)分配出去,另一个(8-15)加入8字节的空闲链表。
  • 下次再分配8字节时,直接从8字节链表取走8-15的块即可。

关键细节:依托数组的链表实现

因为你不能用new,所有链表必须用数组下标维护:

  • 每个大小的空闲链表可以用两个变量(存在数组的固定位置,比如开头)记录头下标和尾下标。
  • 每个空闲块的头部元数据区,用两个位置分别存prev和next的数组下标——比如块A的next是块B的起始下标,块B的prev是块A的起始下标,这样就形成了链表结构,完全不需要额外的内存分配。

内容的提问来源于stack exchange,提问作者Druudik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:42:47