内存片¶
内存片(memory slab) 是一个内核对象,它允许从指定的内存区域上动态地分配内存块(memory block)。同一个内存片上面的所有内存块的尺寸是固定(相同)的,这样做的好处是可以高效地分配和释放,避免了内存碎片问题。
概念¶
可以定义任意数量的内存片。每个内存片通过其内存地址进行引用。
内存片的关键属性包括:
- 块大小: 每个块的尺寸,单位是字节。它必须大于 4N 字节,其中 N 大于 0。
- 块数量:该内存片上可分配的块的数量。它必须大于 0。
- buffer:内存片的块的实际内存区域。它必须大于 “块大小” x “块数量”。
内存片的 buffer 必须 N 字节对齐,其中 N 是大于 2 的 2 的整数次幂(例如 4,8,16...)。为了保证 buffer 中的所有内存块都对齐到这个边界,块的大小必须是 N 的整数倍。
内存片必须先初始化再使用。初始化时会将所有的块标记为未使用。
当线程需要内存块时,它只需要从一个内存片中申请。当线程使用完内存块后,它必须将其释放给原内存片,让其可以重复利用。
如果当前所有的内存块都在使用中,线程可以等待,直到某个块可用。多个线程可以同时等待某个空的内存片;当某个内存块可用时,它会被分配给优先级最高的、等待时间最久的线程使用。
与堆不同的是,如果有需要,可以定义多个内存片。这样的好处是可以定义块大小不同的内存片。也可以使用内存池对象。
实现¶
定义内存片¶
使用类型为 struct 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
在编译期间就定义并初始化一个内存片。
下面的代码与上面的代码片段具有相同的作用。注意到,该宏即定义了它的内存片,也定义了它的 buffer。
K_MEM_SLAB_DEFINE(my_slab, 400, 6, 4);