FreeRTOS--堆内存管理(二)
堆內(nèi)存管理代碼具體實現(xiàn)
- heap_1
 - 內(nèi)存申請函數(shù)
 - 內(nèi)存釋放函數(shù)
 
- heap_2
 - 內(nèi)存塊
 - 內(nèi)存堆初始化函數(shù)
 - 內(nèi)存塊插入函數(shù)
 - 內(nèi)存申請函數(shù)
 - 判斷是不是第一次申請內(nèi)存
 - 開始分配內(nèi)存
 - 內(nèi)存釋放函數(shù)
 
- heap_3
 - heap_4
 - 內(nèi)存堆初始化函數(shù)
 - 內(nèi)存塊插入函數(shù)
 
- heap_5
 
上一篇文章說了FreeRTOS實現(xiàn)堆內(nèi)存的原理,這一篇文章說一下常用函數(shù)的代碼的具體實現(xiàn)。
heap_1
heap_1的內(nèi)存堆為ucHeap[],大小為configTOTAL_HEAP_SIZE
內(nèi)存申請函數(shù)
heap_1的內(nèi)存申請函數(shù)pvPortMalloc()源碼如下:
/*-----------------------------------------------------------*/void * pvPortMalloc( size_t xWantedSize ) {void * pvReturn = NULL;static uint8_t * pucAlignedHeap = NULL;/* Ensure that blocks are always aligned. */#if ( portBYTE_ALIGNMENT != 1 ){if( xWantedSize & portBYTE_ALIGNMENT_MASK ){/* Byte alignment required. Check for overflow. */if ( (xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) )) > xWantedSize ){xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );}else{xWantedSize = 0;}}}#endifvTaskSuspendAll();{if( pucAlignedHeap == NULL ){/* Ensure the heap starts on a correctly aligned boundary. */pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) & ucHeap[ portBYTE_ALIGNMENT - 1 ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );}/* Check there is enough room left for the allocation and. */if( ( xWantedSize > 0 ) && /* valid size */( ( 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();}}#endifreturn pvReturn; } /*-----------------------------------------------------------*/下面的代碼塊是判斷內(nèi)存塊是否對齊
void * pvPortMalloc( size_t xWantedSize ) {void * pvReturn = NULL;static uint8_t * pucAlignedHeap = NULL;/* Ensure that blocks are always aligned. */#if ( portBYTE_ALIGNMENT != 1 ){if( xWantedSize & portBYTE_ALIGNMENT_MASK ) /***** 令 length = portBYTE_ALIGNMENT_MASK二進制中1的個數(shù)* x = xWantedSize的后length位的值* y = portBYTE_ALIGNMENT_MASK-x+1* 如果 xWantedSize & portBYTE_ALIGNMENT_MASK = 0,則xWantedSize肯定是(portBYTE_ALIGNMENT_MASK+1)的整數(shù)倍* 如果 xWantedSize & portBYTE_ALIGNMENT_MASK不為0,則xWantedSize的后length位肯定有1,xWantedSize不是portBYTE_ALIGNMENT_MASK的整數(shù)倍* 如果 xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) )大于xWantedSize,說明后length位肯定有1* xWantedSize = xWantedSize + y,xWantedSize變成portBYTE_ALIGNMENT整數(shù)倍******/{/* Byte alignment required. Check for overflow. */if ( (xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) )) > xWantedSize ){xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );}else{xWantedSize = 0;}}}#endif#if ( portBYTE_ALIGNMENT != 1 )是判斷是否進行字節(jié)對齊,portBYTE_ALIGNMENT默認為8:
 
因為portBYTE_ALIGNMENT 定義為8,所以portBYTE_ALIGNMENT_MASK 定義為0x0007,xWantedSize 是無符號整數(shù)類型(unsigned int),即32位,xWantedSize 與宏portBYTE_ALIGNMENT_MASK 進行與運算來判斷xWantedSize是否為portBYTE_ALIGNMENT 的整數(shù)倍,如果等于0就說明xWantedSizr是portBYTE_ALIGNMENT 的整數(shù)倍,否則的話將xWantedSize加上一個值,讓xWantedSize 變成portBYTE_ALIGNMENT 的整數(shù)倍。具體可以看一下代碼,我加了注釋。
 調(diào)用vTaskSuspendAll()掛起任務調(diào)度器,因為申請內(nèi)存過程中要做保護,不能被其他任務打斷。
pucAlignedHeap是一個靜態(tài)變量,下面這個代碼是初試化pucAlignedHeap,pucAlignedHeap指向ucHeap[ portBYTE_ALIGNMENT - 1 ]
if( pucAlignedHeap == NULL ){/* Ensure the heap starts on a correctly aligned boundary. *//**** 初始化pucAlignedHeap,pucAlignedHeap指向ucHeap[ portBYTE_ALIGNMENT - 1 ]**/pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) & ucHeap[ portBYTE_ALIGNMENT - 1 ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );}接下來就是分配內(nèi)存了,最后返回pvReturn,是分配內(nèi)存的首地址,其中xNextFreeByte是靜態(tài)變量,表示堆ucHeap已經(jīng)用了多少內(nèi)存,configADJUSTED_HEAP_SIZE= configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT,是可以用的內(nèi)存容量。還有如果剩余內(nèi)存小于portBYTE_ALIGNMENT,也是不會創(chuàng)建成功的,也就說是,最后的堆可能有內(nèi)存碎片,下面也一樣。
內(nèi)存釋放函數(shù)
void vPortInitialiseBlocks( void ) {/* Only required when static memory is not cleared. */xNextFreeByte = ( size_t ) 0; }可以看出vPortFree并沒有具體釋放內(nèi)存的過程,因此如果使用heap_1,一旦申請內(nèi)存成功就不允許釋放。
heap_2
heap_2的內(nèi)存堆為ucHeap[],大小為configTOTAL_HEAP_SIZE
內(nèi)存塊
為了實現(xiàn)內(nèi)存釋放,heap_2引入內(nèi)存塊的概念,每分出去的一段內(nèi)存就是內(nèi)存塊,為了管理內(nèi)存塊,引入了一個鏈表結構,此鏈表是來連接空閑塊的,鏈表中的空閑塊順序是根據(jù)空閑塊內(nèi)存的大小排列,鏈表結構如下:
/* Define the linked list structure. This is used to link free blocks in order* of their size. */ typedef struct A_BLOCK_LINK {struct A_BLOCK_LINK * pxNextFreeBlock; /*<< The next free block in the list. */size_t xBlockSize; /*<< The size of the free block. */ } BlockLink_t;為了管理該列表,FreeRTOS定義兩個靜態(tài)變量,xStart、xEnd分別指向鏈表的頭和尾:
/* Create a couple of list links to mark the start and end of the list. */ static BlockLink_t xStart, xEnd;內(nèi)存堆初始化函數(shù)
內(nèi)存堆初始化函數(shù)為pvHeapInit()
static void prvHeapInit( void ) {BlockLink_t * pxFirstFreeBlock;uint8_t * pucAlignedHeap;/* Ensure the heap starts on a correctly aligned boundary. */pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) & ucHeap[ portBYTE_ALIGNMENT - 1 ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );/* xStart is used to hold a pointer to the first item in the list of free* blocks. The void cast is used to prevent compiler warnings. */xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;xStart.xBlockSize = ( size_t ) 0;/* xEnd is used to mark the end of the list of free blocks. */xEnd.xBlockSize = configADJUSTED_HEAP_SIZE;xEnd.pxNextFreeBlock = NULL;/* To start with there is a single free block that is sized to take up the* entire heap space. */pxFirstFreeBlock = ( void * ) pucAlignedHeap;pxFirstFreeBlock->xBlockSize = configADJUSTED_HEAP_SIZE;pxFirstFreeBlock->pxNextFreeBlock = &xEnd; }同heap_1一樣,pucAlignedHeap指向ucHeap[ portBYTE_ALIGNMENT - 1 ],xStart.pxNextFreeBlock指向pucAlignedHeap ,內(nèi)存塊大小為0,xEnd指向的內(nèi)存塊大小為configADJUSTED_HEAP_SIZE,pxNextFreeBlock 的值為NULL,第一個內(nèi)存塊pxFirstFreeBlock 指向pucAlignedHeap,大小為configADJUSTED_HEAP_SIZE,pxNextFreeBlock 指向xEnd。
內(nèi)存塊插入函數(shù)
#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \{ \BlockLink_t * pxIterator; \size_t xBlockSize; \\xBlockSize = pxBlockToInsert->xBlockSize; \\/* Iterate through the list until a block is found that has a larger size */ \/* than the block we are inserting. */ \for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock ) \{ \/* There is nothing to do here - just iterate to the correct position. */ \} \\/* Update the list to include the block being inserted in the correct */ \/* position. */ \pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; \pxIterator->pxNextFreeBlock = pxBlockToInsert; \}就是在一個排好序的鏈表中插入一個數(shù)據(jù),xStart最小,for循環(huán)一直找到鏈表中空閑內(nèi)存塊大于pxBlockToInsert內(nèi)存塊大小的內(nèi)存塊,然后插入進去
內(nèi)存申請函數(shù)
void * pvPortMalloc( size_t xWantedSize ) {BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink;static BaseType_t xHeapHasBeenInitialised = pdFALSE;void * pvReturn = NULL;vTaskSuspendAll();{/* If this is the first call to malloc then the heap will require* initialisation to setup the list of free blocks. */if( xHeapHasBeenInitialised == pdFALSE ){prvHeapInit();xHeapHasBeenInitialised = pdTRUE;}/* The wanted size must be increased so it can contain a BlockLink_t* structure in addition to the requested amount of bytes. */if( ( xWantedSize > 0 ) &&( ( xWantedSize + heapSTRUCT_SIZE ) > xWantedSize ) ) /* Overflow check */{xWantedSize += heapSTRUCT_SIZE;/* Byte alignment required. Check for overflow. */if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) )> xWantedSize ){xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );}else{xWantedSize = 0;}}else{xWantedSize = 0;}if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ){/* Blocks are stored in byte order - traverse the list from the start* (smallest) block until one of adequate size is found. */pxPreviousBlock = &xStart;pxBlock = xStart.pxNextFreeBlock;while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ){pxPreviousBlock = pxBlock;pxBlock = pxBlock->pxNextFreeBlock;}/* If we found the end marker then a block of adequate size was not found. */if( pxBlock != &xEnd ){/* Return the memory space - jumping over the BlockLink_t structure* at its start. */pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );/* This block is being returned for use so must be taken out of the* list of free blocks. */pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;/* If the block is larger than required it can be split into two. */if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ){/* This block is to be split into two. Create a new block* following the number of bytes requested. The void cast is* used to prevent byte alignment warnings from the compiler. */pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );/* Calculate the sizes of two blocks split from the single* block. */pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;pxBlock->xBlockSize = xWantedSize;/* Insert the new block into the list of free blocks. */prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );}xFreeBytesRemaining -= pxBlock->xBlockSize;}}traceMALLOC( pvReturn, xWantedSize );}( void ) xTaskResumeAll();#if ( configUSE_MALLOC_FAILED_HOOK == 1 ){if( pvReturn == NULL ){extern void vApplicationMallocFailedHook( void );vApplicationMallocFailedHook();}}#endifreturn pvReturn; }判斷是不是第一次申請內(nèi)存
xHeapHasBeenInitialised是一個靜態(tài)變量,初始值為pdFALSE,根據(jù)xHeapHasBeenInitialised判斷是不是第一個調(diào)用pvPortMalloc,如果是,即xHeapHasBeenInitialised=pdFALSE,則調(diào)用初始化函數(shù)prvHeapInit(),然后將xHeapHasBeenInitialised設置為pdTRRE。
開始分配內(nèi)存
判斷xWantedSize是否大于0,不是的話則xWantedSize=0。在大于0 的情況下,xWantedSize要加上heapSTRUCT_SIZE,heapSTRUCT_SIZE是一個static const類型,值為8,是為了來存儲一個BlockLink_t結構,同樣分配的內(nèi)存大小也必須是portBYTE_ALIGNMENT的整數(shù)倍。
if( ( xWantedSize > 0 ) &&( ( xWantedSize + heapSTRUCT_SIZE ) > xWantedSize ) ) /* Overflow check */{xWantedSize += heapSTRUCT_SIZE;/* Byte alignment required. Check for overflow. */if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) )> xWantedSize ){xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );}else{xWantedSize = 0;}}如果xWantedSize>0并且xWantedSize要小于xFreeBytesRemaining,xFreeBytesRemaining是一個靜態(tài)類型變量,表示剩下的可用字節(jié)數(shù)(所有空閑塊大小之和)。
 接著按照空閑塊大小,從小到大,依次遍歷,直到找到一個空閑塊,其大小大于等于xWantedSize(此時的xWantedSize=一開始請求的xWantedSize+sizeof(BlockLink_t)),找到滿足所需內(nèi)存塊pxBlock,pxPreviousBlock的pxPreviousBlock就指向pxBlock,如果pxBlock不是指向xEnd,就分配內(nèi)存,pvReturn指向 (pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize的地址,跳過了BlockLink_t,如果pxBlock剩余的內(nèi)存大于secureheapMINIMUM_BLOCK_SIZE,則將剩余的內(nèi)存設置成一個新的空閑內(nèi)存塊,新的空閑內(nèi)存塊用 pxNewBlockLink 表示,pxNewBlockLink指向新的內(nèi)存塊的首地址,接著調(diào)用prvInsertBlockIntoFreeList,將pxNewBlockLink插入到空閑鏈表中。
接著更新xFreeBytesRemaining,xBlockSize=請求的xWantedSize+sizeof(BlockLink_t)
xFreeBytesRemaining -= pxBlock->xBlockSize;最后如果使用hook函數(shù),就調(diào)用vApplicationMallocFailedHook()
內(nèi)存釋放函數(shù)
void vPortFree( void * pv ) {uint8_t * puc = ( uint8_t * ) pv;BlockLink_t * pxLink;if( pv != NULL ){/* The memory being freed will have an BlockLink_t structure immediately* before it. */puc -= heapSTRUCT_SIZE;/* This unexpected casting is to keep some compilers from issuing* byte alignment warnings. */pxLink = ( void * ) puc;vTaskSuspendAll();{/* Add this block to the list of free blocks. */prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );xFreeBytesRemaining += pxLink->xBlockSize;traceFREE( pv, pxLink->xBlockSize );}( void ) xTaskResumeAll();} }puc為要釋放的內(nèi)存首地址,這就是申請內(nèi)存返回的pvReturn所指向的地址,所以必須減去heapSTRUCT_SIZE才是要釋放的內(nèi)存段所在內(nèi)存塊的首地址。pxLink 指向真正的釋放的內(nèi)存首地址,將pxLink插入到空閑塊鏈表中,更新xFreeBytesRemaining 。
heap_3
這個分配方法是對標準C庫中的mallco和free函數(shù)簡單封裝,FreeRTOS對這兩個函數(shù)做了線程保護,不分析了。
heap_4
heap_4提供了最優(yōu)的匹配算法,并且會將碎片合并成一個大的可用內(nèi)存塊,它提供了內(nèi)存塊合并算法
內(nèi)存堆初始化函數(shù)
static void prvHeapInit( void ) /* PRIVILEGED_FUNCTION */ {BlockLink_t * pxFirstFreeBlock;uint8_t * pucAlignedHeap;size_t uxAddress;size_t xTotalHeapSize = configTOTAL_HEAP_SIZE;/* Ensure the heap starts on a correctly aligned boundary. */uxAddress = ( size_t ) ucHeap;if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 ){uxAddress += ( portBYTE_ALIGNMENT - 1 );uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;}pucAlignedHeap = ( uint8_t * ) uxAddress;/* xStart is used to hold a pointer to the first item in the list of free* blocks. The void cast is used to prevent compiler warnings. */xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;xStart.xBlockSize = ( size_t ) 0;/* pxEnd is used to mark the end of the list of free blocks and is inserted* at the end of the heap space. */uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;uxAddress -= xHeapStructSize;uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );pxEnd = ( void * ) uxAddress;pxEnd->xBlockSize = 0;pxEnd->pxNextFreeBlock = NULL;/* To start with there is a single free block that is sized to take up the* entire heap space, minus the space taken by pxEnd. */pxFirstFreeBlock = ( void * ) pucAlignedHeap;pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;pxFirstFreeBlock->pxNextFreeBlock = pxEnd;/* Only one block exists - and it covers the entire usable heap space. */xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;/* Work out the position of the top bit in a size_t variable. */xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); }首先對申請的內(nèi)存做字節(jié)對齊處理,pucAlignedHeap 為內(nèi)存堆字節(jié)對齊以后的可用起始地址,初始化xStart、pxEnd,同heap_2一樣,內(nèi)存塊前面會有一個BlockLink_t類型的變量來描述內(nèi)存塊,這里是完成pxFirstFreeBlock 的初始化,xMinimumEverFreeBytesRemaining 記錄最小的空閑內(nèi)存塊大小,xFreeBytesRemaining 表示內(nèi)存堆剩余大小,初始化靜態(tài)變量xBlockAllocatedBit
內(nèi)存塊插入函數(shù)
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) /* PRIVILEGED_FUNCTION */ {BlockLink_t * pxIterator;uint8_t * puc;/* Iterate through the list until a block is found that has a higher address* than the block being inserted. */for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ){/* Nothing to do here, just iterate to the right position. */}/* Do the block being inserted, and the block it is being inserted after* make a contiguous block of memory? */puc = ( uint8_t * ) pxIterator;if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ){pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;pxBlockToInsert = pxIterator;}else{mtCOVERAGE_TEST_MARKER();}/* Do the block being inserted, and the block it is being inserted before* make a contiguous block of memory? */puc = ( uint8_t * ) pxBlockToInsert;if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ){if( pxIterator->pxNextFreeBlock != pxEnd ){/* Form one big block from the two blocks. */pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;}else{pxBlockToInsert->pxNextFreeBlock = pxEnd;}}else{pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;}/* If the block being inserted plugged a gab, so was merged with the block* before and the block after, then it's pxNextFreeBlock pointer will have* already been set, and should not be set here as that would make it point* to itself. */if( pxIterator != pxBlockToInsert ){pxIterator->pxNextFreeBlock = pxBlockToInsert;}else{mtCOVERAGE_TEST_MARKER();} }下面的代碼是遍歷空閑內(nèi)存塊鏈表,找出當前內(nèi)存塊插入點,內(nèi)存塊是按照地址從低到高的順序鏈接在一起
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ){/* Nothing to do here, just iterate to the right position. */}找到插入點以后判斷是否可以和要插入的內(nèi)存塊合并,如果可以的話就合并在一起,接著檢查是否可以和下一個內(nèi)存塊合并,如果可以就再次合并,如果不能就將這兩個內(nèi)存塊連接起來,pxIterator不等于pxBlockToInsert就意味著在內(nèi)存塊插入的過程中 沒有進行過一次內(nèi)存合并這樣的話就使用最普通的處理方法,pxIterator所指向的內(nèi)存塊在前,pxBlockToinsert所指向的內(nèi)存塊在后,將兩個內(nèi)存塊鏈接起來。
heap_5
heap_5 使用了和heap_4相同的合并算法,內(nèi)存管理實現(xiàn)起來基本相同,但是heap_5內(nèi)存堆跨越多個不連續(xù)的內(nèi)存段,在使用heap_5調(diào)用API函數(shù)之前需要調(diào)用vPortDefineHeapRegions來對內(nèi)存做初始化處理,在vPortDefineHeapRegions未執(zhí)行之前禁止調(diào)用任何可能會調(diào)用pvPortMalloc的API函數(shù)。vPortDefineHeapRegions的參數(shù)是一個HeapRegion_t類型的數(shù)組,HeapRegion是一個結構體:
typedef struct HeapRegion {uint8_t * pucStartAddress; //內(nèi)存塊的起始地址 size_t xSizeInBytes; //內(nèi)存段大小 } HeapRegion_t;總結
以上是生活随笔為你收集整理的FreeRTOS--堆内存管理(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 同步器多少钱啊?
 - 下一篇: VisualStudio2019配置Op