目录
概要
1 概念
2 内部操作
3 实现
3.1 定义
4 参考链接
本学笔记基于zephyr 工程版本 2.2.99,主机环境为ubuntu18.04,开发平台 nrf52840dk_nrf52840
概要
memory slab是一个内核对象,它允许从指定的区域分配一个内存块。所有在内存中的内存块大小都是固定的,允许这些内存块被高效的分配和释放,并且避免了产生内存碎片。简单的来说就是,有一大块内存,分成N个大小固定的小块,这些块由memory slab去管理。应用程序中使用都已一个或多个小块为单位。
1 概念
任意数量的memory slabs可以被定义,引用memory slab,使用的是他的地址。
memory slab有以下关键属性:
block size:以字节为单位必须是4N个字节长度,N必须大于0;
number of blocks:可以有效被分配块的个数,必须大于0;
buffer:就是需要被memory slab管理的那一大块内存。它的大小至少是block size乘以number of blocks。
这个memory slab的buffer必须是N字节对齐,N大于2,而且是2的幂数(比如2,4,8,16,32......),确保所有的内存块也是按照这个方式对齐,块大小必须是N的数。
memory slab使用之前必须被初始化,初始化会标记每一个块为未使用状态。
需要使用内存块的线程,从memory slab分配内存是非常简单的。当线程使用完块内存,那么需要主动释放这块内存,也就是还给memory slab。这样这个块可以被重新使用。
如果所有的内存块,现在都在被使用。那么线程再去请求分配内存块,就会进入睡眠。多个线程可以同时等待一个空的memory slab变为有效。当memory slab变得有效,那个优先级最高且等待时间最长的线程优先被唤醒使用内存块。
和堆不一样,如果有需要,多个memory slab可以被定义。而且memory salb使用大点的块还是小点的块可以自己定义。或者momory pool(后面会提到)也可以这样使用。
2 内部操作
memory slab的buffer是有多个固定块的数组,块与块之间不会浪费空间。
memory slab维护了一个内有被分配使用块的链表。当这个块没有被分配,他的第一个word(4字节)用于链表连接。简单的理解就是当这个块被memory slab使用的时候(就是没分配),那么他的前四个字节被memory slab用于链表使用。当这个块分配给应用程序的时候,那么这个块都不归memory slab管了,所以不管是前4个字节或是整个块,应用程序可以随便用。当应用程序释放这个块的时候,那么memory slab又把这个块的前四个字节占用,存储链表信息。这个链表上挂的都是内有被使用的块。
3 实现
3.1 定义
可以使用struct k_mem_slab()类型定义一个memory slab变量。它必须使用k_mem_slab_init()去初始化。
下面的代码示例,初始化一个memory slab。这个memory slab包含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);
3.2 分配一个内存块
使用k_mem_slab_alloc()分配一个内存块。
下面的代码示例,分配一个内存块,如果不能分配最多等待100ms,如果分配成功把内存块初始化为0:
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");
3.3 释放一个内存块
可以使用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);
4 参考链接
https://docs.zephyrproject.org/latest/reference/kernel/memory/slabs.html