RTX笔记10 - 内存池Memory Pool
内存池是线程安全的固定大小的内存块。它们的运行速度比动态分配的堆快得多,而且不会出现碎片问题。由于是线程安全的,因此可以从线程和ISR访问它们。
内存池可以看作是固定大小的可用(未使用)内存块的链表。从池中分配内存(使用osMemoryPoolAlloc),只需从列表中解链一个块,并将控制权交给用户。向池释放内存(使用osMemoryPoolFree)只需将块重新链接到列表中。
共享内存是线程间交换信息的基本模型之一。使用内存池交换数据,与消息队列相比,可以在线程之间共享更复杂的对象。内存池管理功能用于定义和管理这种固定大小的内存池。
Note:osMemoryPoolAlloc, osMemoryPoolFree, osMemoryPoolGetCapacity, osMemoryPoolGetBlockSize, osMemoryPoolGetCount, osMemoryPoolGetSpace可以在中断中调用。
1 typedef struct { 2 const char *name; /** 指向内存池的名称 **/ 3 uint32_t attr_bits; /** 保留属性位 **/ 4 void *cb_mem; /** 指向内存池控制块的内存。NULL,使用动态内存分配内存 **/ 5 uint32_t cb_size; /** 内存池控制块的内存大小 **/ 6 void *mp_mem; /** 指向存储数据的内存。NULL,使用动态内存分配内存 **/ 7 uint32_t mp_size; /** 存储数据的内存大小 **/ 8 } osMemoryPoolAttr_t;
osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr)
函数创建并初始化一个内存池对象,并返回指向内存池对象标识符的指针,在出现错误时返回NULL。不能在中断中调用。
输入参数:
block_count:内存块的最大数量。
block_size :内存块的字节大小
attr :内存块属性
返回值:内存块ID,或者NULL。
void * osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout)
申请一个内存块。timeout参数指定系统等待分配内存的时间。当系统等待时,调用此函数的线程将被置于BLOCKED状态。只要至少有一块内存可用,线程就会变成READY。
输入参数:
mq_id :内存池ID。
timeout:等待超时时间。0,函数立即返回;osWaitForever,一直等待,直到消息从消息队列中获取;others,等待的tick数。
返回值:返回申请的内存地址,如果没有足够的内存池可以申请则返回NULL。
Note:用户使用内存块时要注意内存块的大小,不能越界使用;如果超时时间设置为0,则可以在中断中调用。
osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block)
释放内存块,放回内存池中。
输入参数:
mq_id :内存池ID。
block:已分配的要返回给内存池的内存块的地址。
返回值:
osOK:内存块已经被释放会内存池。
osErrorParameter:mp_id参数错误,block指向不可用的内存。
osErrorResource:内存池处于不可用状态。
Note:osMemoryPoolFree可能会对给定的块指针执行某些检查。但是使用osMemoryPoolFree释放的指针不是从osMemoryPoolAlloc申请的指针,会有UNPREDICTED行为。可以在中断中调用。
osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id)
删除一个内存池。
返回值:
osOK:内存池已经被删除。
osErrorParameter:mp_id参数错误。
osErrorResource:内存池处于不可用状态。
osErrorISR:中断中调用错误。
1 #define OBJ_NBR_MAX 6 2 3 typedef struct { 4 uint8_t ix; 5 uint32_t buf[8]; 6 } Obj; 7 8 osMemoryPoolId_t mem_pool; 9 10 static void _ledThread(void *argument); 11 12 void 13 testMemPool(void) 14 { 15 mem_pool = osMemoryPoolNew(OBJ_NBR_MAX, sizeof(Obj), NULL); 16 osThreadNew(_ledThread, NULL, NULL); 17 } 18 19 static void 20 _ledThread(void *argument) 21 { 22 Obj *obj; 23 24 argument = (void *)0; 25 26 for(;;) { 27 obj = (Obj *)osMemoryPoolAlloc(mem_pool, 10); 28 if(NULL != obj) { 29 obj->ix = 1; 30 obj->buf[0] = (uint32_t)argument; 31 argument = (void *)((uint32_t)argument + 1); 32 menuShow(&seg_led, obj->buf[0], 0); 33 osMemoryPoolFree(mem_pool, obj); 34 } 35 osDelay(1000); 36 } 37 }