全部文档
OneOS简介 硬件支持 快速开发指南 编译构造工具 API参考文档 高级语言 用户编程手册 应用笔记 FAQ

内存池管理


简介

内存池适用于分配大量大小相同的内存块的场景,它能够快速的分配和释放内存,且能够尽量避免内存碎片化。内存池在创建时需要有一块大内存,在初始化时把这块大内存划分成大小相等的小内存块,并用链表连接起来。用户可根据实际需要创建多个内存池,不同内存池中的内存块大小可以不同。

内存池还支持任务挂起功能,即当内存池中无空闲内存块时,申请的任务会被阻塞,直到该内存池有可用内存块,任务才会被唤醒。这个特性比较适合需要通过内存资源进行同步的场景。


重要定义及数据接口

宏定义

#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 在该内存池申请内存时阻塞的任务

API列表

接口 说明
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_mp_init

该函数使用静态的方式初始化内存池,内存池对象及内存池空间由使用者提供,函数原型如下:

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_deinit

该函数反初始化内存池,唤醒被阻塞任务,与os_mp_init()匹配使用,函数原型如下:

os_err_t os_mp_deinit(os_mp_t *mp);
参数 说明
mp 内存池句柄
返回 说明
OS_EOK 反初始化成功

os_mp_create

该函数动态创建并初始化内存池,内存池对象的空间及内存池空间都通过动态申请内存的方式获取,函数原型如下:

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_destroy

该函数销毁内存池,唤醒被阻塞的任务,释放内存池空间和内存池对象的空间,与os_mp_create()匹配使用,函数原型如下:

os_err_t os_mp_destroy(os_mp_t *mp);
参数 说明
mp 内存池句柄
返回 说明
OS_EOK 销毁成功

os_mp_alloc

该函数从内存池中申请一块内存,若暂时无法获取且设置了等待时间,则当前任务会阻塞,函数原型如下:

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_free

该函数释放由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

results matching ""

    No results matching ""