内存块分配器允许从指定的内存区域动态分配内存块,其中:

  • 所有内存块都有一个固定大小。
  • 可以同时分配或释放多个块。
  • 一组内存块可能不是连续的。这对于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字节边界对齐:

  1. SYS_MEM_BLOCKS_DEFINE(allocator, 64, 4, 4);

也可以在静态区域里定义内存块:

  1. SYS_MEM_BLOCKS_DEFINE_STATIC(static_allocator, 64, 4, 4);

还可以向分配器提供预定义的缓冲区。请注意,缓冲区的对齐需要在其定义时完成

  1. uint8_t __aligned(4) backing_buffer[64 * 4];
  2. SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(allocator, 64, 4, backing_buffer);

分配内存块

可以通过调用sys_mem_blocks_alloc()来分配内存块。

  1. int ret;
  2. uintptr_t blocks[2];
  3. ret = sys_mem_blocks_alloc(allocator, 2, blocks);

释放内存块

通过调用sys_mem_blocks_free()释放内存块。

  1. int ret;
  2. uintptr_t blocks[2];
  3. ret = sys_mem_blocks_alloc(allocator, 2, blocks);
  4. ... /* perform some operations on the allocated memory blocks */
  5. ret = sys_mem_blocks_free(allocator, 2, blocks);

使用多内存块分配器组

定义多内存块分配器组:

  1. sys_mem_blocks_t *choice_fn(struct sys_multi_mem_blocks *group, void *cfg)
  2. {
  3. ...
  4. }
  5. SYS_MEM_BLOCKS_DEFINE(allocator0, 64, 4, 4);
  6. SYS_MEM_BLOCKS_DEFINE(allocator1, 64, 4, 4);
  7. static sys_multi_mem_blocks_t alloc_group;
  8. sys_multi_mem_blocks_init(&alloc_group, choice_fn);
  9. sys_multi_mem_blocks_add_allocator(&alloc_group, &allocator0);
  10. sys_multi_mem_blocks_add_allocator(&alloc_group, &allocator1);

从组中分配和释放内存块:

  1. int ret;
  2. uintptr_t blocks[1];
  3. size_t blk_size;
  4. ret = sys_multi_mem_blocks_alloc(&alloc_group, UINT_TO_POINTER(0),
  5. 1, blocks, &blk_size);
  6. ret = sys_multi_mem_blocks_free(&alloc_group, 1, blocks);