伙伴算法分配器在分配时,会将内存不断地二等分,直到切割到能满足内存的最小尺寸为止。 释放时会检查与之相邻并等长的内存块(称为伙伴)是否空闲, 如果是,就和“伙伴”合并成更大的内存块, 然后继续检测合并后的内存块是否也存在空闲的伙伴,一直向上合并到不能合并为止。
- 优点:
- 支持释放操作;
- 支持大小不固定的内存申请操作;
- 内存碎片的大小只会是单位内存块大小的2的n次方倍,内存碎片更容易被合并。
- 缺点:
- 代码稍微复杂;
- 因为存在合并与切割的循环,申请与释放操作的所需要的时间不是特别稳定;
- 内存大小固定为2的指数,如果申请的内存过小,会造成内存浪费。
- 适用性:对内存复用性要求高的应用场合。
- 上下文的安全性:在任何上下文(中断、中断底半部、线程)都是安全的。
◆ XWMM_BMA_COMBINED
#define XWMM_BMA_COMBINED ((xwu8_t)127) |
◆ XWMM_BMA_INUSED
#define XWMM_BMA_INUSED ((xwu8_t)0x80) |
◆ XWMM_BMA_MAX_ORDER
#define XWMM_BMA_MAX_ORDER ((xwu8_t)126) |
◆ XWMM_BMA_ORDER_MASK
#define XWMM_BMA_ORDER_MASK ((xwu8_t)0x7F) |
◆ XWMM_BMA_RAWOBJ_DEF
#define XWMM_BMA_RAWOBJ_DEF |
( |
|
name, |
|
|
|
blkodr |
|
) |
| |
值:
定义伙伴算法内存块分配器结构体的RAW内存空间, 用于初始化伙伴算法内存块分配器结构体
- 参数
-
[in] | name | 内存数组名 |
[in] | blkodr | 伙伴算法内存块分配器中单位内存块的数量,以2的blkodr次方形式表示 |
在文件 bma.h 第 55 行定义.
◆ xwmm_bma_alloc()
XWMM API:申请一块连续的内存
- 参数
-
[in] | bma | 伙伴算法内存块分配器对象的指针 |
[in] | order | 块数量的阶,内存块大小: ((1 << order) * bma->blksize) |
[out] | membuf | 指向地址缓存的指针,通过此指针缓存返回申请到的内存的首地址 |
- 返回
- 错误码
- 返回值
-
-EFAULT | 空指针 |
-ERANGE | order无效 |
-ENOMEM | 内存不足 |
- 注解
- 同步/异步:同步
- 上下文:中断、中断底半部、线程
- 重入性:可重入
<No error
在文件 bma.c 第 311 行定义.
312{
318
322
330 break;
331 }
332 }
337 } else {
339 "[ALLOC] bcb(idx:0x%lX,odr:0x%X)\n",
347 }
348 return rc;
349}
static struct xwmm_bma_bcb * xwmm_bma_orderlist_choose(struct xwmm_bma *bma, struct xwmm_bma_orderlist *ol)
从阶链表中选择一块内存,并返回其块控制块
#define xwmm_bmalogf(lv, fmt,...)
static void * xwmm_bma_bcb_to_mem(struct xwmm_bma *bma, struct xwmm_bma_bcb *bcb)
从内存块的控制块指针获得内存块的首地址
static void xwmm_bma_divide_block(struct xwmm_bma *bma, struct xwmm_bma_bcb *bcb, xwsq_t target_odr, struct xwmm_bma_orderlist *curr_ol)
将大内存块分割成小块
#define ENOENT
No such file or directory
#define EFAULT
Bad address
#define ENOMEM
Not enough space
#define ERANGE
Result too large
static __xwcc_inline void *__xwcc_must_check err_ptr(xwer_t err)
将错误码转换为指针
static __xwcc_inline bool __xwcc_must_check is_err(const void *ptr)
测试指针的值是否为错误码
static void xwos_splk_unlock_cpuirqrs(struct xwos_splk *spl, xwreg_t cpuirq)
XWOS API:解锁自旋锁,并恢复本地CPU的中断标志
static void xwos_splk_lock_cpuirqsv(struct xwos_splk *spl, xwreg_t *cpuirq)
XWOS API:上锁自旋锁,保存本地CPU的中断标志并关闭
#define XWOS_VALIDATE(exp, errstr,...)
检查函数参数是否有效
struct xwmm_bma_orderlist * orderlists
struct xwmm_bma_bcb * bcbs
◆ xwmm_bma_free()
XWMM API:释放内存块
- 参数
-
[in] | bma | 伙伴算法内存块分配器对象的指针 |
[in] | mem | 内存块的首地址指针 |
- 返回
- 错误码
- 返回值
-
XWOK | 没有错误 |
-EINVAL | 参数错误 |
-ERANGE | 内存块不属于指定的伙伴算法内存块分配器对象 |
- 注解
- 同步/异步:同步
- 上下文:中断、中断底半部、线程
- 重入性:可重入
< 块正在被使用
<No error
在文件 bma.c 第 402 行定义.
403{
407
410
411 if ((((
xwptr_t)mem < bma->zone.origin) ||
414 goto err_range;
415 }
419 goto err_invalmem;
420 }
422 "[FREE] mem:0x%lX,bcb(idx:0x%lX,odr:0x%X)\n",
429 goto err_invalmem;
430 }
435
436err_invalmem:
437err_range:
438 return rc;
439}
static struct xwmm_bma_bcb * xwmm_bma_mem_to_bcb(struct xwmm_bma *bma, void *mem)
从内存块首地址获得其控制块的指针
static void xwmm_bma_combine(struct xwmm_bma *bma, struct xwmm_bma_bcb *bcb)
合并内存块
#define EINVAL
Invalid argument
static __xwcc_inline xwer_t __xwcc_must_check ptr_err(const void *ptr)
将指针的值转换为错误码
◆ xwmm_bma_init()
XWMM API:初始化伙伴算法内存块分配器
- 参数
-
[in] | bma | 伙伴算法内存块分配器的指针 |
[in] | name | 名字 |
[in] | origin | 内存区域的起始地址 |
[in] | size | 内存区域的大小 |
[in] | blksize | 伙伴算法内存块分配器中单位内存块的大小 |
[in] | blkodr | 伙伴算法内存块分配器中单位内存块的数量,以2的blkodr次方形式表示 |
- 返回
- 错误码
- 返回值
-
- 注解
- 单位内存块的数量只能是2的n次方,即
2, 4, 8, 16, 32, 64, 128, ...
,对应的 blkodr
分别为 1, 2, 3, 4, 5, 6, 7, ...
;
- 内存区域大小必须满足关系:
size == (blksize * (1 << blkodr))
。
-
- 同步/异步:同步
- 上下文:中断、中断底半部、线程
- 重入性:不可重入
<Size error
< 块正在被使用
< 块已被合并
< 块正在被使用
<No error
在文件 bma.c 第 62 行定义.
65{
69
71
72 num = 1U << blkodr;
73 if (size != (num * blksize)) {
75 xwmm_bmalogf(ERR,
"Size of memory(0x%lX, 0x%lX) is error!\n",
76 origin, size);
77 goto err_size;
78 }
88 "memory:(0x%lX,0x%lX),orderlists:0x%lX,bcbs:0x%lX,"
89 "blocksize:0x%lX, blockorder:0x%lX\n",
92
93 for (i = 0; i < num; i++) {
95 }
97
98 for (i = 0; i <= blkodr; i++) {
100 }
103
104err_size:
105 return rc;
106}
static void xwmm_bma_orderlist_add(struct xwmm_bma *bma, struct xwmm_bma_orderlist *ol, xwu8_t odr, struct xwmm_bma_bcb *bcb)
将一块内存加入到阶链表
#define XWMM_BMA_COMBINED
static void xwlib_bclst_init_head(struct xwlib_bclst_node *h)
初始化一个链表头。
static void xwos_splk_init(struct xwos_splk *spl)
XWOS API:初始化自旋锁
struct xwlib_bclst_node head