本篇內容主要講解“FreeRTOS動態內存分配管理示例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“FreeRTOS動態內存分配管理示例分析”吧!
FreeRTOS提供5種動態內存管理策略,分別為heap_1到heap_5,源碼在FreeRTOS/Source/portable/MemMang下,本質是對一個或者多個大數組進行操作來對系統提供內存的申請、釋放(有的策略沒有)功能。下面先看看heap_1是怎么做的。
大數組在哪里
/* Allocate the memory for the heap. */ #if( configAPPLICATION_ALLOCATED_HEAP == 1 ) //這種情況是可以把待管理的數組分配在外部SRAM、SDRAM中 extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; #else //這種情況是把待管理的數組分配在內部RAM,由編譯器決定地址 static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; #endif /* configAPPLICATION_ALLOCATED_HEAP */
可以看到這個局部靜態全局大數組名字是ucHeap,大小是configTOTAL_HEAP_SIZE,這個宏在FreeRTOSConfig.h中定義
//因為需要字節對齊,所以實際能使用的內存字節數要減去portBYTE_ALIGNMENT /* A few bytes might be lost to byte aligning the heap start address. */ #define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )
portBYTE_ALIGNMENT 在portmacro.h中定義
#define portBYTE_ALIGNMENT8
已分配字節數
//已經分配了的字節數,也就是下一個空閑內存相對于首址(pucAlignedHeap)的偏移量 static size_t xNextFreeByte = ( size_t ) 0;
void *pvPortMalloc( size_t xWantedSize )
{
void *pvReturn = NULL;//待返回給用戶分配地址
static uint8_t *pucAlignedHeap = NULL;//實際管理的數組首地址
/* Ensure that blocks are always aligned to the required number of bytes. */
//如果不是1字節對齊則先需要portBYTE_ALIGNMENT字節對齊
#if( portBYTE_ALIGNMENT != 1 )
{
if( xWantedSize & portBYTE_ALIGNMENT_MASK )
{ /* Byte alignment required. */
//如果用戶申請字節數不是portBYTE_ALIGNMENT_MASK字節對齊的,先要調整到portBYTE_ALIGNMENT_MASK字節對齊
//比如申請13字節,要求portBYTE_ALIGNMENT = 8,
//則xWantedSize = 13+(8-(13&7))=13+(8-5)=16,
//最終申請16字節
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
}
}
#endif
//掛起調度器,防止函數重入
vTaskSuspendAll();
{
if( pucAlignedHeap == NULL )
//說明是第一次調用此函數需要對對內存堆初始化確保內存堆首址也是8字節對齊
{
/* Ensure the heap starts on a correctly aligned boundary. */
//假設&ucHeap是0x20000C64,
//則&ucHeap[ portBYTE_ALIGNMENT ]是 0x20000C64+7=0x20000C6B
//pucAlignedHeap = 0x20000C6B & (~0x00000007) = 0x20000C68
//pucAlignedHeap才是實際操作的堆首址
pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
}
/* Check there is enough room left for the allocation. */
//已經分配的字節數xNextFreeByte + 將要分配的字節數xWantedSize
//要小于總共有的字節數configADJUSTED_HEAP_SIZE
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;
}其中portBYTE_ALIGNMENT_MASK是根據portBYTE_ALIGNMENT定義,在portable.h中
#if portBYTE_ALIGNMENT == 8 #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) #endif
可以看到heap_1是沒有提供釋放,是無法釋放的
void vPortFree( void *pv )
{
/* Memory cannot be freed using this scheme. See heap_2.c, heap_3.c and
heap_4.c for alternative implementations, and the memory management pages of
http://www.FreeRTOS.org for more information. */
( void ) pv;
/* Force an assert as it is invalid to call this function. */
configASSERT( pv == NULL );
}size_t xPortGetFreeHeapSize( void )
{
return ( configADJUSTED_HEAP_SIZE - xNextFreeByte );
}適用范圍、特點
適用于只需分配,不需釋放場合,執行時間確定,不會產生碎片,但是內存利用率不高
到此,相信大家對“FreeRTOS動態內存分配管理示例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。