Slabs
是一个内核对象,它允许从指定的内存区域动态分配内存块。内存板中的所有内存块都具有单一的固定大小,允许有效地分配和释放它们,并避免内存碎片问题。
概念
可以定义任意数量的内存板(仅受可用 RAM 的限制)。每个内存板都由其内存地址引用。
内存板具有以下关键属性:
- 每个块的块大小,以字节为单位。它必须至少为4N字节长,其中N大于0。
- 可用于分配的块数。它必须大于零。
- 为内存板块提供内存的缓冲区。它必须至少是
块大小
乘以块数
字节的长度。
内存板的缓冲区必须与N字节边界对齐,其中N是大于2的2次幂(即 4、8、16、…)。要确保缓冲区中的所有内存块都与此边界对齐,块大小也必须是N的倍数。
必须先初始化内存板,然后才能使用它。这会将其所有块标记为未使用。
需要使用内存块的线程只需从内存板中分配它。当线程使用内存块完成时,它必须将块释放回内存板,以便可以重用该块。
如果所有块当前都在使用中,则线程可以选择等待一个块变为可用。任意数量的线程可以同时在空内存板上等待;当内存块变为可用时,它将被提供给等待时间最长的优先级最高的线程。
与堆不同,如果需要,可以定义多个内存板
。这允许内存板具有较小的块,而其他内存板具有较大的块。或者,可以使用内存池对象。
内部操作
内存板的缓冲区是固定大小的块的数组,块之间没有浪费空间。
内存板使用链表跟踪未分配的块;每个未使用块的前4个字节提供必要的链接。
定义内存板
内存板是使用k_mem_slab
类型定义的变量。然后必须通过调用k_mem_slab_init()
对其进行初始化。
下面的代码定义并初始化一个内存板
,该内存板具有6个块,这些块的长度为400字节,每个块都与4字节边界对齐。
struct k_mem_slab my_slab;
char __aligned(4) my_slab_buffer[6 * 400];
k_mem_slab_init(&my_slab, my_slab_buffer, 400, 6);
也可以通过调用K_MEM_SLAB_DEFINE
在编译时定义和初始化内存板。
K_MEM_SLAB_DEFINE(my_slab, 400, 6, 4);
也可以将缓冲区放在静态区域里,通过K_MEM_SLAB_DEFINE_STATIC
宏来定义内存板。
K_MEM_SLAB_DEFINE_STATIC(my_slab, 400, 6, 4);
分配内存块
通过调用k_mem_slab_alloc()
来分配内存块。
以下的代码最多等待 100 毫秒,以便内存块变为可用,然后用零填充该内存块。如果未获得合适的块,则会打印警告。
char *block_ptr;
if (k_mem_slab_alloc(&my_slab, &block_ptr, 100) == 0)) {
memset(block_ptr, 0, 400);
...
} else {
printf("Memory allocation time-out");
}
释放内存块
通过调用k_mem_slab_free()
释放内存块。
char *block_ptr;
k_mem_slab_alloc(&my_slab, &block_ptr, K_FOREVER);
... /* use memory block pointed at by block_ptr */
k_mem_slab_free(&my_slab, &block_ptr);
内存板的Kconfig
Kconfig | 描述 |
---|---|
CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION | 这为k_mem_slab 结构增加了可变性,以使内存版获得最大利用率。 |