1.简介
内存分配在RTOS上还是较为常见的,除了一些特殊场合使用的RTOS(不允许malloc,free操作,防止内存碎片), 实际产品中,使用分配内存机制还是较常用。
RTOS上的内存管理方式,分为常见的动态内存堆管理,和静态内存池管理,其中动态内存管理又分为常见的,小内存分配算法,多内存分配算法(memheap),
slab分配算法等等。RT-Thread上分配算法可以在conf中配置。
RT_USING_SMALL_MEM_AS_HEAP 小内存分配算法
RT_USING_MEMHEAP_AS_HEAP 内存堆分配
RT_USING_SLAB_AS_HEAP SLAB分配算法
2.RTT上统一的内存接口
上述已经提及常见的几种内存分配算法,针对内存堆管理,RTT对应用层提供了统一的调用API.(备注RTT最新的分配算法和早期有差异)
2.1 初始化堆内存
/**
* @brief This function will init system heap.
*
* @param begin_addr the beginning address of system page.
*
* @param end_addr the end address of system page.
*/
RT_WEAK void rt_system_heap_init(void *begin_addr, void *end_addr)
{
//针对设定的起始,结束地址,做一个4字节对齐
rt_ubase_t begin_align = RT_ALIGN((rt_ubase_t)begin_addr, RT_ALIGN_SIZE);
rt_ubase_t end_align = RT_ALIGN_DOWN((rt_ubase_t)end_addr, RT_ALIGN_SIZE);
RT_ASSERT(end_align > begin_align);
/* Initialize system memory heap */
//这里会根据用户设置内存分配算法,初始化内存分配算法
_MEM_INIT("heap", begin_addr, end_align - begin_align);
/* Initialize multi thread contention lock */
//初始化内存分配互斥锁(大多数场景都有mutex,如果没有,也需要采取进临界措施)
_heap_lock_init();
}
对于mcu起始heap地址,在bsp层都会定义清楚。参考:
#if defined(__ARMCC_VERSION)
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
#elif __ICCARM__
#pragma section="CSTACK"
#define HEAP_BEGIN (__segment_end("CSTACK"))
#else
extern int __bss_end;
#define HEAP_BEGIN ((void *)&__bss_end)
#endif
2.2 分配内存接口
RT_WEAK void *rt_malloc(rt_size_t size)
{
rt_base_t level;
void *ptr;
/* Enter critical zone */
//使用互斥锁,在没有的情况进临界区,关闭中断
level = _heap_lock();
/* allocate memory block from system heap */
//调用统一的接口进行分配(根据不同的分配算法进行)
ptr = _MEM_MALLOC(size);
/* Exit critical zone */
//解除互斥锁
_heap_unlock(level);
/* call 'rt_malloc' hook */
RT_OBJECT_HOOK_CALL(rt_malloc_hook, (ptr, size));
return ptr;
}
2.3 释放分配的内存
RT_WEAK void rt_free(void *rmem)
{
rt_base_t level;
/* call 'rt_free' hook */
RT_OBJECT_HOOK_CALL(rt_free_hook, (rmem));
/* NULL check */
if (rmem == RT_NULL) return;
/* Enter critical zone */
//进临界,对内存进行操作
level = _heap_lock();
_MEM_FREE(rmem);
/* Exit critical zone */
//退出临界
_heap_unlock(level);
}
2.4 其它接口
其它一些接口进行内存的重新分配,分配并初始化为0。
//分配并清0
RT_WEAK void *rt_calloc(rt_size_t count, rt_size_t size);
//打印内存信息
RT_WEAK void rt_memory_info(rt_size_t *total,
rt_size_t *used,
rt_size_t *max_used);
//重新分配
RT_WEAK void *rt_realloc(void *rmem, rt_size_t newsize);
3.说明
从上描述的源码可以看到,进行内存分配的时候会考虑临界区,在线程中使用时,会使用mutex进行互斥。 所以对于在中断里面不要使用内存分配和释放接口。 附带(RTT4.0+版本,操作heap使用mutex源码):
rt_inline rt_base_t _heap_lock(void)
{
#if defined(RT_USING_HEAP_ISR)
return rt_hw_interrupt_disable();
#elif defined(RT_USING_MUTEX)
if (rt_thread_self())
//当前处于线程中,需要进行临界保护
return rt_mutex_take(&_lock, RT_WAITING_FOREVER);
else
//在非线程中,例如中断
return RT_EOK;
#else
rt_enter_critical();
return RT_EOK;
#endif
}
您还没有登录,请您登录后发表评论。