堆内存池

堆内存池(heap memory pool) 是一个预定义的内存池对象,它允许线程像使用 malloc() 那样从一段通用内存区动态地申请内存。

概念

堆内存池只能定义一个。与其它内存池不同的是,堆内存池不能通过内存地址对其引用。

堆内存池的大小是可配置的,支持如下大小:256 字节,1024 字节,4096 字节和 16384 字节。

线程可以调用函数 k_malloc() 来动态申请一大块堆内存。所分配的地址是 4 字节对齐的。如果内核没有找到合适的内存块,将返回一个 NULL

当线程使用完堆内存后,它应当调用 k_free() 将其释放到堆内存池中。

内部操作

堆内存池定义了一个包含整个堆的单一的最大尺寸块;即单一块的大小是 256、1024、4096 或 16384 字节。堆内存池也定义了一个最小尺寸块 —— 64 字节。下表展示了堆内存池在每种块尺寸下所能支持的块的数量。

堆 尺寸 64 字节 的块 256 字节 的块 1024 字节 的块 4096 字节 的块 16384 字节 的块
256 4 1 0 0 0
1024 16 4 1 0 0
4096 64 16 4 1 0
16384 256 64 16 4 1

注解

对于某个给定的尺寸的内存块,能同时分配到的数量通常小于上面的表所列举的结果。例如,每当从大小为 1024 字节的堆内存中分配一个大小为 256 字节的块后,所能分配到的大小为 64 字节的块的数量就会减 4。内存池 buffer 中的碎片也会进一步减小可用块的数量。

内存块被分配后,它的前 16 个字节将被内核用于记录块描述符。内核随后会使用该描述符释放块。因此,如果应用程序请求的堆内存大小是 N 字节,实际至少会使用 N+16 字节。

实现

定义堆内存池

配置选项 CONFIG_HEAP_MEM_POOL_SIZE 用于指定堆内存池的大小。

默认情况下,堆内存池的大小是零字节,它指示内核不要去定义堆内存池对象。

分配

函数 k_malloc() 用于分配一块堆内存。

下面的代码先申请了 200 字节的堆内存空间,然后将其填充为零。如果没有获取到所需的空间,它将打印一条警告消息。

注意,应用程序实际会接收到一个大小为 256 字节的内存块,因为这是堆内存池所支持的最接近的尺寸。

char *mem_ptr;

mem_ptr = k_malloc(200);
if (mem_ptr != NULL)) {
    memset(mem_ptr, 0, 200);
    ...
} else {
    printf("Memory not allocated");
}

释放内存

函数 k_free() 用于释放一块堆内存。

下面的代码申请了 75 字节的内存块,并在不再使用时释放。(基于安全考虑,实际上会从堆内存池使用 256 字节的内存块。)

char *mem_ptr;

mem_ptr = k_malloc(75);
... /* use memory block */
k_free(mem_ptr);

建议的用法

您可以像使用 malloc() 那样使用堆内存池动态地分配内存。

配置选项

相关的配置选项:

  • CONFIG_HEAP_MEM_POOL_SIZE

API

头文件 kernel.h 中提供了如下的堆内存池 API:

  • k_malloc()
  • k_free()