内存块
分配器允许从指定的内存区域动态分配内存块,其中:
- 所有内存块都有一个固定大小。
- 可以同时分配或释放多个块。
- 一组内存块可能不是连续的。这对于DMA传输等操作非常有用。
- 已分配块的标记在相关缓冲区之外完成(与内存板不同)。
概念
可以定义任意数量的内存块分配器(仅受可用 RAM 的限制)。每个分配器都由其内存地址引用。
内存块分配器具有以下关键属性:
- 每个块的块大小,以字节为单位。它必须至少为4N字节长,其中N大于 0。
- 可用于分配的块数。它必须大于零。
- 为内存板块提供内存的缓冲区。它必须至少是
块大小
乘以块数
字节的长度。 - 一个块位图,用于跟踪已分配的块。
缓冲区必须与 N 字节边界对齐,其中 N 是大于 2的2次幂(即 4、8、16、…)。要确保缓冲区中的所有内存块都与此边界对齐,块大小也必须是N的倍数。
内部操作
与分配器关联的每个缓冲区都是一个固定大小的块数组,块之间不会浪费空间。
内存块分配器使用位图跟踪未分配的块。
内存块分配器
在内部,内存块分配器使用位图来跟踪已分配的块。每个分配器利用sys_bitarray
接口,从备份缓冲区逐个获取内存块,直至请求的块数。有关分配器的所有元数据都存储在后备缓冲区之外。
多内存块分配器组
多内存块分配器组提供了管理一组分配器的便捷功能。自定义分配器选择函数用于选择要在此组中使用的分配器。
分配器组应在运行时通过sys_multi_mem_blocks_init()
进行初始化。然后可以通过sys_multi_mem_blocks_add_allocator()
添加每个分配器。
要从组中分配内存块,请使用不透明的configuration
参数调用sys_multi_mem_blocks_alloc()
。此参数直接传递给分配器选择函数
,以便可以选择适当的分配器。选择分配器后,通过sys_mem_blocks_alloc()
分配内存块。
分配的内存块可以通过sys_multi_mem_blocks_free()
释放。调用方不需要传递配置参数。分配器代码匹配传入的内存地址以找到正确的分配器,然后通过sys_mem_blocks_free()
释放内存块。
定义内存块分配器
内存块分配器是使用sys_mem_blocks_t
类型的变量定义的。它需要在编译时通过调用SYS_MEM_BLOCKS_DEFINE
来定义和初始化。
下面的代码定义并初始化一个内存块分配器,该分配器具有4个64字节长的块,每个块都与4字节边界对齐:
SYS_MEM_BLOCKS_DEFINE(allocator, 64, 4, 4);
也可以在静态区域里定义内存块:
SYS_MEM_BLOCKS_DEFINE_STATIC(static_allocator, 64, 4, 4);
还可以向分配器提供预定义的缓冲区。请注意,缓冲区的对齐需要在其定义时完成
uint8_t __aligned(4) backing_buffer[64 * 4];
SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(allocator, 64, 4, backing_buffer);
分配内存块
可以通过调用sys_mem_blocks_alloc()
来分配内存块。
int ret;
uintptr_t blocks[2];
ret = sys_mem_blocks_alloc(allocator, 2, blocks);
释放内存块
通过调用sys_mem_blocks_free()
释放内存块。
int ret;
uintptr_t blocks[2];
ret = sys_mem_blocks_alloc(allocator, 2, blocks);
... /* perform some operations on the allocated memory blocks */
ret = sys_mem_blocks_free(allocator, 2, blocks);
使用多内存块分配器组
定义多内存块分配器组:
sys_mem_blocks_t *choice_fn(struct sys_multi_mem_blocks *group, void *cfg)
{
...
}
SYS_MEM_BLOCKS_DEFINE(allocator0, 64, 4, 4);
SYS_MEM_BLOCKS_DEFINE(allocator1, 64, 4, 4);
static sys_multi_mem_blocks_t alloc_group;
sys_multi_mem_blocks_init(&alloc_group, choice_fn);
sys_multi_mem_blocks_add_allocator(&alloc_group, &allocator0);
sys_multi_mem_blocks_add_allocator(&alloc_group, &allocator1);
从组中分配和释放内存块:
int ret;
uintptr_t blocks[1];
size_t blk_size;
ret = sys_multi_mem_blocks_alloc(&alloc_group, UINT_TO_POINTER(0),
1, blocks, &blk_size);
ret = sys_multi_mem_blocks_free(&alloc_group, 1, blocks);