1、内存管理简介
在计算机系统中,变量、中间数据一般存放在系统存储空间中,只有在实际使用时才将它们从存储空间调入到中央处理器内部进行运算。通常存储空间可以分为两种:内部存储空间和外部存储空间。内部存储空间访问速度比较快,能够按照变量地址随机地访问,也就是我们通常所说的RAM(随机存储器),或电脑的内存;而外部存储空间内所保存的内容相对来说比较固定,即使掉电后数据也不会丢失,可以把它理解为电脑的硬盘。
我们主要讨论内部存储空间(RAM)的管理--内存管理。
在嵌入式程序设计中内存分配应该是根据所设计系统的特点来决定选择使用动态内存分配还是静态内存分配算法,一些可靠新要求非常高的系统应选择使用静态的,而普通的业务系统可以使用动态来提高内存使用效率。静态可以保证设备的可靠性但是需要考虑内存上线,内存使用效率低,而动态则是相反。
FreeRTOS内存管理模块管理用于系统中内存资源,他是操作系统的核心模块之一。主要包括内存的初始化、分配以及释放。
除了FreeRTOS提供的动态内存管理方法,标准的C库也提供了函数malloc()和函数free()来实现动态地申请和释放内存,那为啥不用标准的C库自带的内存管理算法呢?
因为标准C库的动态内存管理方法有如下几个缺点:
(1)占用大量的代码空间,不适合用在资源紧缺的嵌入式系统中。
(2)没有线程安全的相关机制。
(3)运行有不确定性,每次调用这些函数时花费的时间可能都不相同。
(4)内存碎片化。
因此,FreeRTOS提供了多种动态内存管理的算法,可针对不同的嵌入式系统。
2、FreeRTOS内存管理算法
heap_1内存管理算法
heap_1只实现了pvPortMalloc,而没有实现vPortFree;也就是说,它只能申请内存,无法释放内存。
如果你的工程,创建好的任务、队列、信号量等都不需要被删除,那么可以使用heap_1内存管理算法。
heap_1的实现最为简单,管理的内存堆是一个数组,在申请内存的时候,heap_1内存管理算法只是简单地从数组中分出合适大小的内存,内存堆数组的定义如下所示:
heap_2内存管理算法
相比于heap_1内存管理算法,heap_2内存管理算法使用最适应算法,并且支持释放内存;
heap_2内存管理算法并不能将相邻的空间内存块合并成一个大的空间内存块;因此heap_2内存管理算法不可避免地会产生内存碎片;
最适应算法:
假设heap有三块空闲内存(按内存块大小由小到大排序):5字节、25字节、50字节。
现在就创建一个任务需要申请20字节的内存。
第一步:找出最小的、能满足pvPortMalloc的内存:25字节。
第二步:把它划分为20字节、5字节;返回这20字节的地址,剩下的5字节仍然是空闲状态,留给后续的pvPortMalloc使用。
heap_4内存管理算法
heap_4内存管理算法使用了首次适应算法,也支持内存的申请与释放,并且能够将空闲且相邻的内存进行合并,从而减少内存碎片化的现象。
首次适应算法:
假设heap_4有3块空闲内存(按内存块地址由低到高排序):5字节、50字节、25字节。
现在创建一个任务需要申请20字节的内存。
第一步:找出第一个能满足pvPortMalloc的内存:50字节。
第二步:把它划分为20字节、30字节;返回这20字节的地址,剩下30字节仍然是空闲状态,留给和后续的pvPortMalloc使用。
heap_5内存管理算法
heap_5内存管理算法是在heap_4内存管理算法的基础上实现的,但是heap_5内存管理算法在heap_4内存管理算法的基础上实现了管理多个非连续内存区域的能力。
heap_5内存管理算法默认并没有定义内存堆,需要用户手动指定内存区域的信息,对其进行初始化。
如何定义一块内存?
使用如下结构体:
怎么指定多块且不连续的内存?