以下为看视频笔记..........
1. 内存池的介绍
动态内存堆可以分配任意大小的内存块,非常灵活和方便。但其存在明显的缺点:一是分配效率不高,在每次分配时,都要进行空闲内存块查找;二是容易产生内存碎片。
为了提高内存分配的效率,并且避免内存碎片,RT-Thread 提供了另外一种内存管理方法:内存池(Memory Pool )
内存池是一种内存分配方式,用于分配大量大小相同的小内存块。使用内存池可以极大地加快内存分配与释放的速度,且能尽量避免内存碎片化。
RT-Thread的内存池支持线程挂起功能,当内存池中无空闲内存块时,申请线程会被挂起,直到内存池中有新的可用内存块,再将挂起的线程唤醒。基于这个特点内存池非常适合需要通过内存资源进行同步的场景。
2. 内存池工作机制
内存池在创建时先从系统中获取一大块内存 ( 静态或动态),然后分成相同大小的多个小内存块,这些小内存块通过链表连接起来(此链表也称为空闲链表)。线程每次申请分配内存块的时候,系统从空闲链表中取出链头上第一个内存块, 提供给申请者。
3. 内存池控制块
在RT_Thread中,内存池控制块是操作系统用于管理内存池的一个数据结构。
struct rt_mempool
{
struct rt_object parent:
void *start_address;//保存申请的内存的地址
rt_size_t size; //记录大内存块的大小
rt_size_t block_size; //记录大内存块中小内存块的大小
rt_uint8_t *block_list; //小内存块的列表
rt_size_t block_total_count;//总共有多少小内存块
rt_size_t block_free_count; //当前小内存块空闲的个数
rt_list_t suspend_thread; //内存块支持挂起,记录线程挂起在内存池上的列表
rt_size_t suspend_thread_count;//记录线程挂起在内存池上的数目
}
typedef struct rt_mempool *rt_mp_t //内存块的指针型定义
定义静态内存池:struct rt_mempool static_mp
定义动态内存池:rt_mp_t dynamic_mp
4. 内存池的操作
静态内存池的初始化与脱离
rt_err_t rt_mp_init(struct rt_mempool *mp,const char *name,
void *start,rt_size_t size,rt_size_t block_size)
//第一个参数为内存控制块的地址,第二个参数为内存控制块起一个名字,注意RT-Thread的所有对象都要起一个名称。第三个参数为系统的内存地址输入给参数,可以先用数组的方式定义出来。第四个参数为内存池的大小。第五个参数为内存池中内存块的大小(数值为4的整数倍)。计算内存池中有多少内存块:
//size/(block_size+4).内存块都是用链表连接的,4是一个指针的长度
rt_err_t rt_mp_detach(struct rt_mempool *mp)
//第二个参数为内存块数目。第三个参数为内存块的大小
动态内存池的创建与删除
rt_mp_t rt_mp_create(const char *name,rt_size_t block_count,rt_size_t block_size)
rt_err_t rt_mp_delete(rt_mp_t mp)
申请内存块
void rt_mp_alloc(rt_mp_t mp ,rt_int32_t time)
//第一个参数为内存块控制块的地址,指示从哪个内存池分配内存控制块,第二个参数为当内存池满时线程挂起时间,当time>0,挂起time 时间,当time = 0,立即返回,time < 0 ,线程阻塞在内存池的申请上。
释放内存块
void rt_mp_free(void *block)//输入内存块的地址,释放那个内存块
5. 例程在memp_sample.c