文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

FreeRTOS动态内存分配管理heap_1示例

2024-04-02 19:55

关注

动态内存管理

FreeRTOS提供5种动态内存管理策略,分别为heap_1到heap_5,源码在FreeRTOS/Source/portable/MemMang下,本质是对一个或者多个大数组进行操作来对系统提供内存的申请、释放(有的策略没有)功能。下面先看看heap_1是怎么做的。

heap_1.c 内存堆管理

大数组在哪里


#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
//这种情况是可以把待管理的数组分配在外部SRAM、SDRAM中
	extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#else
//这种情况是把待管理的数组分配在内部RAM,由编译器决定地址
	static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#endif 

可以看到这个局部静态全局大数组名字是ucHeap,大小是configTOTAL_HEAP_SIZE,这个宏在FreeRTOSConfig.h中定义

实际可用数组字节数

//因为需要字节对齐,所以实际能使用的内存字节数要减去portBYTE_ALIGNMENT

#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;//实际管理的数组首地址
	
    //如果不是1字节对齐则先需要portBYTE_ALIGNMENT字节对齐
	#if( portBYTE_ALIGNMENT != 1 )
	{
		if( xWantedSize & portBYTE_ALIGNMENT_MASK )
		{			
		//如果用户申请字节数不是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字节对齐
		{
			
		    //假设&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 ) ) );
		}
		
		//已经分配的字节数xNextFreeByte + 将要分配的字节数xWantedSize
		//要小于总共有的字节数configADJUSTED_HEAP_SIZE
		if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&
		//此条件是防止溢出,因为内存是地址是单调增长
			( ( xNextFreeByte + xWantedSize ) > xNextFreeByte )	)
		{
			
			//返回地址给用户
			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 )
{
	
	( void ) pv;
	
	configASSERT( pv == NULL );
}

还剩空闲字节数

size_t xPortGetFreeHeapSize( void )
{
	return ( configADJUSTED_HEAP_SIZE - xNextFreeByte );
}

适用范围、特点

适用于只需分配,不需释放场合,执行时间确定,不会产生碎片,但是内存利用率不高

以上就是FreeRTOS动态内存分配管理heap_1示例的详细内容,更多关于FreeRTOS动态内存分配管理的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯