Q群:
电话:
邮箱:
地址:
内存池适用于分配大量大小相同的内存块的场景,它能够快速的分配和释放内存,且能够尽量避免内存碎片化。内存池在创建时需要有一块大内存,在初始化时把这块大内存划分成大小相等的小内存块,并用链表连接起来。用户可根据实际需要创建多个内存池,不同内存池中的内存块大小可以不同。
内存池还支持任务挂起功能,即当内存池中无空闲内存块时,申请的任务会被阻塞,直到该内存池有可用内存块,任务才会被唤醒。这个特性比较适合需要通过内存资源进行同步的场景。
#define OS_MEM_WAITING_FOREVER ((os_tick_t)0xFFFFFFFF)
#define OS_MEM_WAITING_NO ((os_tick_t)0)
定义 | 说明 |
---|---|
OS_MEM_WAITING_FOREVER | 申请不到内存时,永久等待 |
OS_MEM_WAITING_NO | 申请不到内存时,不等待 |
struct os_mempool
{
os_object_t parent; /* inherit from os_object */
void *start_address; /* memory pool start */
os_size_t size; /* size of memory pool */
os_size_t block_size; /* size of memory blocks */
os_uint8_t *block_list; /* memory blocks list */
os_size_t block_total_count; /* numbers of memory block */
os_size_t block_free_count; /* numbers of free memory block */
os_list_node_t suspend_task; /* tasks pended on this resource */
};
参数 | 说明 |
---|---|
start_address | 内存池的起始地址 |
size | 内存池的大小 |
block_size | 该内存池中每个内存块的大小 |
block_list | 内存块的链表,指向下一个空闲内存块 |
block_total_count | 内存块的总数 |
block_free_count | 空闲内存块的个数 |
suspend_task | 在该内存池申请内存时阻塞的任务 |
接口 | 说明 |
---|---|
os_mp_init | 使用静态的方式初始化内存池,内存池对象及内存池空间由使用者提供 |
os_mp_deinit | 反初始化内存池,与os_mp_init()匹配使用 |
os_mp_create | 动态创建并初始化内存池,内存池对象的空间及内存池空间通过动态申请获取 |
os_mp_destroy | 销毁内存池,与os_mp_create()匹配使用 |
os_mp_alloc | 从内存池中申请一块内存 |
os_mp_free | 释放内存到内存池中,与os_mp_alloc()匹配使用 |
该函数使用静态的方式初始化内存池,内存池对象及内存池空间由使用者提供,函数原型如下:
os_err_t os_mp_init(os_mp_t *mp,
const char *name,
void *start,
os_size_t size,
os_size_t block_size);
参数 | 说明 |
---|---|
mp | 内存池句柄 |
name | 内存池名字 |
start | 内存池起始地址 |
size | 内存池大小 |
block_size | 每个内存块的大小 |
返回 | 说明 |
OS_EOK | 初始化成功 |
该函数反初始化内存池,唤醒被阻塞任务,与os_mp_init()匹配使用,函数原型如下:
os_err_t os_mp_deinit(os_mp_t *mp);
参数 | 说明 |
---|---|
mp | 内存池句柄 |
返回 | 说明 |
OS_EOK | 反初始化成功 |
该函数动态创建并初始化内存池,内存池对象的空间及内存池空间都通过动态申请内存的方式获取,函数原型如下:
os_mp_t *os_mp_create(const char *name,
os_size_t block_count,
os_size_t block_size);
参数 | 说明 |
---|---|
name | 内存池名字 |
block_count | 内存块的个数 |
block_size | 每个内存块的大小 |
返回 | 说明 |
非OS_NULL | 创建成功,返回内存池句柄 |
OS_NULL | 创建失败 |
该函数销毁内存池,唤醒被阻塞的任务,释放内存池空间和内存池对象的空间,与os_mp_create()匹配使用,函数原型如下:
os_err_t os_mp_destroy(os_mp_t *mp);
参数 | 说明 |
---|---|
mp | 内存池句柄 |
返回 | 说明 |
OS_EOK | 销毁成功 |
该函数从内存池中申请一块内存,若暂时无法获取且设置了等待时间,则当前任务会阻塞,函数原型如下:
void *os_mp_alloc(os_mp_t *mp, os_tick_t timeout);
参数 | 说明 |
---|---|
mp | 内存池句柄 |
timeout | 暂无空闲内存块时的等待时间;若为OS_MEM_WAITING_NO,则不等待直接返回OS_NULL;若为OS_MEM_WAITING_FOREVER,则永久等待直到有内存块可用;若为其它,则等待timeout时间或者直到有内存块可用 |
返回 | 说明 |
非OS_NULL | 分配成功,返回内存块的地址 |
OS_NULL | 分配失败 |
该函数释放由os_mp_alloc()申请的内存块,函数原型如下:
void os_mp_free(void *block);
参数 | 返回 |
---|---|
block | 待释放的内存块地址 |
返回 | 说明 |
无 | 无 |
本例初始化了一个静态内存池,并在一个任务中去申请内存块,另外一个任务中去释放内存块
#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <os_task.h>
#include <shell.h>
#include <os_memory.h>
#define TEST_TAG "TEST"
#define TASK_STACK_SIZE 1024
#define TASK1_PRIORITY 15
#define TASK2_PRIORITY 16
#define TASK_TIMESLICE 10
#define TEST_ALLOC_CNT 10
#define BLOCK_SIZE 100
#define POOL_SIZE 500
static os_uint8_t mem_pool[POOL_SIZE];
static os_mp_t mp_static;
void *block_ptr[TEST_ALLOC_CNT];
void task1_entry(void *para)
{
os_uint32_t i = 0;
for (i = 0 ; i < TEST_ALLOC_CNT; i++)
{
LOG_W(TEST_TAG, "task1 try to alloc");
block_ptr[i] = os_mp_alloc(&mp_static, OS_MEM_WAITING_FOREVER);
if (block_ptr[i])
{
LOG_W(TEST_TAG, "task1 alloc:%p", block_ptr[i]);
}
}
}
void task2_entry(void *para)
{
os_uint32_t i = 0;
for (i = 0 ; i < TEST_ALLOC_CNT; i++)
{
LOG_W(TEST_TAG, "task2 free :%p", block_ptr[i]);
os_mp_free(block_ptr[i]);
block_ptr[i] = OS_NULL;
os_task_sleep(200);
}
}
void mempool_static_sample(void)
{
os_task_t *task1 = OS_NULL;
os_task_t *task2 = OS_NULL;
os_mp_init(&mp_static, "mempool_static", &mem_pool, sizeof(mem_pool), BLOCK_SIZE);
task1 = os_task_create("task1",
task1_entry,
OS_NULL,
TASK_STACK_SIZE,
TASK1_PRIORITY,
TASK_TIMESLICE);
if (task1)
{
LOG_W(TEST_TAG, "mempool_static_sample startup task1");
os_task_startup(task1);
}
os_task_sleep(200);
task2 = os_task_create("task2",
task2_entry,
OS_NULL,
TASK_STACK_SIZE,
TASK2_PRIORITY,
TASK_TIMESLICE);
if (task2)
{
LOG_W(TEST_TAG, "mempool_static_sample startup task2");
os_task_startup(task2);
}
}
SH_CMD_EXPORT(static_mempool, mempool_static_sample, "test static mempool");
运行结果如下:
sh />static_mempool
W/TEST: mempool_static_sample startup task1
W/TEST: task1 try to alloc
W/TEST: task1 alloc:200028cc
W/TEST: task1 try to alloc
W/TEST: task1 alloc:20002938
W/TEST: task1 try to alloc
W/TEST: task1 alloc:200029a4
W/TEST: task1 try to alloc
W/TEST: task1 alloc:20002a10
W/TEST: task1 try to alloc
W/TEST: mempool_static_sample startup task2
W/TEST: task2 free :200028cc
W/TEST: task1 alloc:200028cc
W/TEST: task1 try to alloc
W/TEST: task2 free :20002938
W/TEST: task1 alloc:20002938
W/TEST: task1 try to alloc
W/TEST: task2 free :200029a4
W/TEST: task1 alloc:200029a4
W/TEST: task1 try to alloc
W/TEST: task2 free :20002a10
W/TEST: task1 alloc:20002a10
W/TEST: task1 try to alloc
W/TEST: task2 free :200028cc
W/TEST: task1 alloc:200028cc
W/TEST: task1 try to alloc
W/TEST: task2 free :20002938
W/TEST: task1 alloc:20002938
W/TEST: task2 free :200029a4
W/TEST: task2 free :20002a10
W/TEST: task2 free :200028cc
W/TEST: task2 free :20002938
本例动态创建了一个内存池,然后申请和释放内存块
#include <oneos_config.h>
#include <os_dbg.h>
#include <os_errno.h>
#include <shell.h>
#include <string.h>
#include <os_memory.h>
#define TEST_TAG "TEST"
#define BLOCK_CNT 5
#define BLOCK_SIZE 100
static os_mp_t *mp_dynamic;
void mempool_dynamic_sample(void)
{
os_uint32_t i = 0;
void *block_ptr[BLOCK_CNT + 1];
memset(&block_ptr[0], 0, sizeof(block_ptr));
mp_dynamic = os_mp_create("mempool_dynamic", BLOCK_CNT, BLOCK_SIZE);
if (mp_dynamic)
{
LOG_W(TEST_TAG, "mempool_dynamic_sample create mempool, bolock cnt:%d", BLOCK_CNT);
}
for (i = 0; i < BLOCK_CNT + 1; i++)
{
block_ptr[i] = os_mp_alloc(mp_dynamic, OS_MEM_WAITING_NO);
if (block_ptr[i])
{
LOG_W(TEST_TAG, "alloc:%p", block_ptr[i]);
}
else
{
LOG_W(TEST_TAG, "alloc ERR");
}
}
for (i = 0; i < BLOCK_CNT + 1; i++)
{
if (block_ptr[i])
{
LOG_W(TEST_TAG, "free :%p", block_ptr[i]);
os_mp_free(block_ptr[i]);
}
}
LOG_W(TEST_TAG, "mempool_dynamic_sample destroy mempool");
os_mp_destroy(mp_dynamic);
}
SH_CMD_EXPORT(dynamic_mempool, mempool_dynamic_sample, "test dynamic mempool");
运行结果如下:
sh />dynamic_mempool
W/TEST: mempool_dynamic_sample create mempool, bolock cnt:5
W/TEST: alloc:20007870
W/TEST: alloc:200078dc
W/TEST: alloc:20007948
W/TEST: alloc:200079b4
W/TEST: alloc:20007a20
W/TEST: alloc ERR
W/TEST: free :20007870
W/TEST: free :200078dc
W/TEST: free :20007948
W/TEST: free :200079b4
W/TEST: free :20007a20
W/TEST: mempool_dynamic_sample destroy mempool