目录

​概要​

​1 概念​

​2 内部操作​

​3 实现​

​3.1 定义​

​3.2 分配一个内存块​

​3.3 释放一个内存块​

​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​