内存池
1,动态内存堆,可以分配人员大小的内存块,非常方便灵活。
明显缺点:(1)分配效率不高,每次分配都需要进行空闲内存块查找;(2)容易产生内存碎片;
2,为了提供内存分配效率,并且避免内存碎片,RT-Thread提供了另外一种内存管理方法----内存池(Memory Pool);
内存池的内存分配方式是分配大量相同大小的小内存块。使内存池可以极大地加快内存分配和释放的速度,且能尽量避免内存碎片化。
3,RT-Thread的内存池支持线程挂起功能,当内存池中无空闲内存块时,申请线程会被挂起,直到内存池中有新的可用内存块,再将挂起线程唤醒。基于这个特点,内存池非常适合需要通过内存资源进行同步的场景。
内存池工作机制:
内存池在创建的时候先从系统中获取一大块内存(静态或动态),然后分成相同大小的多个小内存块,这些小内存块通过链表连接起来(此链表也称为空闲链表)。线程每次申请分配内存块的时候,系统从空闲链表中取出链头上第一块内存块,提供给申请者。
内存池控制块:
/**
* Base structure of Memory pool object
*/
struct rt_mempool
{
struct rt_object parent; /**< inherit from rt_object */
void *start_address; /**< memory pool start */
rt_size_t size; /**< size of memory pool */
rt_size_t block_size; /**< size of memory blocks */
rt_uint8_t *block_list; /**< memory blocks list */
rt_size_t block_total_count; /**< numbers of memory block */
rt_size_t block_free_count; /**< numbers of free memory block */
rt_list_t suspend_thread; /**< threads pended on this resource */
rt_size_t suspend_thread_count; /**< numbers of thread pended on this resource */
};
typedef struct rt_mempool *rt_mp_t;
--------------------------
定义静态内存池:struct rt_mempool static_mp;
定义动态内存池:rt_mp_t dynamic_mp;
初始化与脱离:
/**
* This function will initialize a memory pool object, normally which is used
* for static object.
*
* @param mp the memory pool object
* @param name the name of memory pool
* @param start the star address of memory pool
* @param size the total size of memory pool
* @param block_size the size for each block
*
* @return RT_EOK
*/
rt_err_t rt_mp_init(struct rt_mempool *mp,
const char *name,
void *start,
rt_size_t size,
rt_size_t block_size);
----------------------------------------------------
/**
* This function will detach a memory pool from system object management.
*
* @param mp the memory pool object
*
* @return RT_EOK
*/
rt_err_t rt_mp_detach(struct rt_mempool *mp);
创建与删除:
/**
* This function will create a mempool object and allocate the memory pool from
* heap.
*
* @param name the name of memory pool
* @param block_count the count of blocks in memory pool
* @param block_size the size for each block
*
* @return the created mempool object
*/
rt_mp_t rt_mp_create(const char *name,
rt_size_t block_count,
rt_size_t block_size);
-------------------------------------------------------
/**
* This function will delete a memory pool and release the object memory.
*
* @param mp the memory pool object
*
* @return RT_EOK
*/
rt_err_t rt_mp_delete(rt_mp_t mp);
申请内存块:
/**
* This function will allocate a block from memory pool
*
* @param mp the memory pool object
* @param time the waiting time
*
* @return the allocated memory block or RT_NULL on allocated failed
*/
void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time);
释放内存块:
/**
* This function will release a memory block
*
* @param block the address of memory block to be released
*/
void rt_mp_free(void *block);
示例代码:
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-24 yangjie the first version
*/
/*
* 程序清单:内存池例程
*
* 这个程序会创建一个静态的内存池对象,2个动态线程。
* 一个线程会试图从内存池中获得内存块,另一个线程释放内存块
* 内存块
*/
#include <rtthread.h>
static rt_uint8_t *ptr[50];
static rt_uint8_t mempool[4096];
static struct rt_mempool mp;
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
/* 指向线程控制块的指针 */
static rt_thread_t tid1 = RT_NULL;
static rt_thread_t tid2 = RT_NULL;
/* 线程1入口 */
static void thread1_mp_alloc(void *parameter)
{
int i;
for (i = 0 ; i < 50 ; i++)
{
if (ptr[i] == RT_NULL)
{
/* 试图申请内存块50次,当申请不到内存块时,
线程1挂起,转至线程2运行 */
ptr[i] = rt_mp_alloc(&mp, RT_WAITING_FOREVER);
if (ptr[i] != RT_NULL)
rt_kprintf("allocate No.%d\n", i);
}
}
}
/* 线程2入口,线程2的优先级比线程1低,应该线程1先获得执行。*/
static void thread2_mp_release(void *parameter)
{
int i;
rt_kprintf("thread2 try to release block\n");
for (i = 0; i < 50 ; i++)
{
/* 释放所有分配成功的内存块 */
if (ptr[i] != RT_NULL)
{
rt_kprintf("release block %d\n", i);
rt_mp_free(ptr[i]);
ptr[i] = RT_NULL;
}
}
}
int mempool_sample(void)
{
int i;
for (i = 0; i < 50; i ++) ptr[i] = RT_NULL;
/* 初始化内存池对象 */
rt_mp_init(&mp, "mp1", &mempool[0], sizeof(mempool), 80);
/* 创建线程1:申请内存池 */
tid1 = rt_thread_create("thread1", thread1_mp_alloc, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY, THREAD_TIMESLICE);
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
/* 创建线程2:释放内存池*/
tid2 = rt_thread_create("thread2", thread2_mp_release, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY + 1, THREAD_TIMESLICE);
if (tid2 != RT_NULL)
rt_thread_startup(tid2);
return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(mempool_sample, mempool sample);
运行结果: