一、简介
LiteOS将内核与内存管理分开实现,操作系统内核仅规定了必要的内存管理函数原型,而不关心这些内存管理函数是如何实现的。
LiteOS内存管理模块管理系统的内存资源,包括:初始化、分配、释放。
不采用C标准库中的内存管理函数malloc和free的原因如下:
- 小型嵌入式设备的RAM不足,导致这些函数在有些情况下无法使用
- 内存管理的函数实现代码量可能非常大,占据了相当大的一块代码空间。
- 不安全,执行时间不确定。
- 容易产生碎片。这两个函数会使得连接器配置变得非常复杂。
内存池是线程安全的固定大小的内存块。它的操作速度比动态分配的堆要快得多,而且不会受到碎片的影响。由于是线程安全的,所以,可以从中断中访问。
内存池可以看做是一个固定大小,且大小相同的内存块的链表。从池中分配内存,只是从列表中解除块链,并将控制权交给用户。释放内存到池,只是将块重新链到空闲链表中。
共享内存是线程间交换信息的基本模型之一。与使用消息队列相比,使用内存池交换数据可以在线程之间共享更复杂的对象。
Memory Pool
二、特点
内存管理模块通过对内存的释放、申请操作,来管理用户和OS对内存的使用。使内存的利用率和使用率达到最优,同时最大限度地解决系统的内存碎片问题。
内存管理分为:静态内存管理和动态内存管理。
静态内存管理:在静态内存池中分配用户初始化时预设(固定)大小的内存块
- 优点:分配和释放效率高,静态内存池中无碎片
- 缺点:只能申请到初始化预设的内存块,不能按需申请。
动态内存:在动态内存池中分配用户指定大小的内存块
- 优点:按需分配
- 缺点:内存池可能会存在碎片
注:小熊派目前使用的都是动态内存的方式。
三、API介绍
osMemoryPoolNew
函数功能:
创建内存池。不能在中断中调用。
函数原型:
osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr);
参数:
block_count:申请的内存块个数
block_size:每个内存块的大小
attr:属性。自定义内存时使用,默认为NULL
返回值:
NULL:失败
其他值:内存池ID
实例:
osMemoryPoolId_t mpid_MemPool = NULL;
mpid_MemPool = osMemoryPoolNew(MEMPOOL_OBJECTS,sizeof(MEM_BLOCK_t),NULL);
osMemoryPoolAlloc
函数功能:
从内存池中申请内存块。如果内存池空,则挂起,直到有内存块可用。如果超时时间为0,可在中断中调用。
函数原型:
void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout);
参数:
mp_id:内存池ID。创建内存池osMemoryPoolNew时获得。
timeout:等待超时时间
返回值:
获取到的内存块地址
实例:
MEM_BLOCK_t *pMem = NULL;
osMemoryPoolId_t mpid_MemPool = NULL;
pMem = osMemoryPoolAlloc(mpid_MemPool,100);
osMemoryPoolFree
函数功能:
释放内存块到内存池中。可在中断中调用。
函数原型:
osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block);
参数:
mp_id:内存池ID。创建内存池osMemoryPoolNew时获得。
block:要释放的内存块地址。osMemoryPoolAlloc的返回值。
返回值:
osOK:成功、
其他值:失败
实例:
osMemoryPoolId_t mpid_MemPool = NULL;
MEM_BLOCK_t *pMem = NULL;
osStatus_t rst = osMemoryPoolFree(mpid_MemPool,pMem);
osMemoryPoolDelete
函数功能:
删除内存池。不能在中断中使用。
函数原型:
osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id);
参数:
mp_id:内存池ID。创建内存池osMemoryPoolNew时获得。
返回值:
osOK:成功、
其他值:失败
实例:
osMemoryPoolId_t mpid_MemPool = NULL;
osStatus_t ret = osMemoryPoolDelete(mpid_MemPool);
四、实例
待补充。