FreeRTOS提供的内存管理都是从内存堆中分配内存的。默认情况下,FreeRTOS内核创建任务、队列、信号量、事件组、软件定时器都是借助内存管理函数从内存堆中分配内存。最新的FreeRTOS版本(V9.0.0及其以上版本)可以完全使用静态内存分配方法,也就是不使用任何内存堆。
对于heap_1.c、heap_2.c和heap_4.c这三种内存管理策略,内存堆实际上是一个很大的数组,定义为: static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
这是5个内存管理策略中最简单的一个,我们称为第一个内存管理策略,它简单到只能申请内存。是的,跟你想的一样,一旦申请成功后,这块内存再也不能被释放。对于大多数嵌入式系统,特别是对安全要求高的嵌入式系统,这种内存管理策略很有用,因为对系统软件来说,逻辑越简单越容易兼顾安全。实际上,大多数的嵌入式系统并不需要动态删除任务、信号量、队列等,而是在初始化的时候一次性创建好,便一直使用,永远不用删除。所以这个内存管理策略实现简洁、安全可靠,使用的非常广泛。我对这个对内存管理策略也情有独钟。
size_t xNextFreeByte = ( size_t ) 0;已经分配内存的大小 static uint8_t *pucAlignedHeap = NULL;指向八字节对齐的的内存位置
申请分配内存=>
void *pvPortMalloc( size_t xWantedSize ) { void *pvReturn = NULL;//static uint8_t *pucAlignedHeap = NULL;
#ifdef __SRAM_SUPPORT__ if (xWantedSize % 2) { xWantedSize += 1; } #endif /*__SRAM_SUPPORT__*/ /* Ensure that blocks are always aligned to the required number of bytes. */保证字节数是8的倍速 #if portBYTE_ALIGNMENT != 1 if( xWantedSize & portBYTE_ALIGNMENT_MASK ) { xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); } #endif
算法总结:X+=8-(X&0111) =>X最终的结果总会是8的倍数。
vTaskSuspendAll(); { if( pucAlignedHeap == NULL )//开第一次分配内存 { /* Ensure the heap starts on a correctly aligned boundary. */ pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); }
/* Check there is enough room left for the allocation. */ if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) && ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check for overflow. */ { /* Return the next free byte then increment the index past this block. */ pvReturn = pucAlignedHeap + xNextFreeByte; xNextFreeByte += xWantedSize; }
traceMALLOC( pvReturn, xWantedSize ); } ( void ) xTaskResumeAll();
#if( configUSE_MALLOC_FAILED_HOOK == 1 ) { if( pvReturn == NULL ) { extern void vApplicationMallocFailedHook( void ); vApplicationMallocFailedHook(); } } #endif
return pvReturn; }