网站管理后台如果在代理商那里接手会不会停掉,给别人做网站赚钱吗,wordpress 内容分页,杭州网站建设多少钱1. 为什么要自己实现内存管理
对于内核对象#xff0c;可以使用时分配#xff0c;不使用时释放C语音的库函数不适应与FreeRTOS: 实现过于复杂#xff0c;占用空间大并非线程安全的运行不确定性#xff1a;每次运算时间不确定内存碎片化不太编译器配置不同调试难
2. 堆栈…1. 为什么要自己实现内存管理
对于内核对象可以使用时分配不使用时释放C语音的库函数不适应与FreeRTOS: 实现过于复杂占用空间大并非线程安全的运行不确定性每次运算时间不确定内存碎片化不太编译器配置不同调试难
2. 堆栈
我们经常说的“堆栈”是两种不同的东西
2.1. 堆
heap就是一块空闲的内存通过malloc、free来管理
2.2. 栈
stack函数调用时局部变量保存在栈中当前的程序环境也保存在栈中可以充堆中分配一块内存用于栈空间
3. FreeRTOS系统5种内存管理方法
文件在 FreeRTOS/Source/portable/MemMang 下5个文件对应5中内存管理方法
3.1. Heap_1
3.1.1. 特点
只实现了pvPortMalloc没有实现vPortFree如果程序中不需要删除内核对象不需要释放内存那么可以实现heap_1
实现最简单没有碎片问题一些要求非常严格的系统中不允许使用动态内存可实现heap_1
3.1.2. 实现原理
定义一个大数组
#if ( configAPPLICATION_ALLOCATED_HEAP 1 )
/* The application writer has already defined the array used for the RTOS
* heap - probably so it can be placed in a special segment or address. */
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#else
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#endif /* configAPPLICATION_ALLOCATED_HEAP */调用pvPortMalloc调用时从数组中分配空间 注意 内存申请时需要字节对齐处理 – 在有些处理器中访问奇地址访问内存会报错 3.2. Heap_2
Heap_2 之所以还保留只是为了兼容以前的代码。新的设计中不再推进实现Heap_2。 Heap_2也是在数组上分配内存和Heap_1不一样的地方在于
heap_2使用最佳匹配算法来分配内存支持vPortFree
3.2.1. 数据结构
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;3.2.2. 内存结构 3.2.3. 最佳匹配算法
假设Heap有3个空闲块5字节、25字节、100字节pvPortMalloc想申请20个字节先找到最小的、能满足要求的内存25字节把它分为20字节、5字节 返回20字节的地址剩下的5字节仍是空闲状态继续留给后续使用
与Heap_4相比Heap_2不会合并相邻的空闲内存所以Heap_2会导致严重的碎片化问题但是如果申请、分配内存大小都相同的场景下Heap_2就没有碎片化问题所以它适合这些场景频繁窗户删除任务、但任务的栈大小都是相同的。 虽然不再推荐使用Heap_2但它的效率还是远高于malloc、free.
3.3. Heap_3
Heap_3 使用标准 C 库里的 malloc、 free 函数C 库里的 malloc、 free 函数并非线程安全的 Heap_3 中先暂停 FreeRTOS 的调度器再去调用这些函数使用这种方法实现了线程安全。
3.4. Heap_4
跟 Heap_1、 Heap_2 一样 Heap_4 也是使用大数组来分配内存。Heap_4 使用首次适应算法(first fit)来分配内存。它还会把相邻的空闲内存合并为一个更大的空闲内存这有助于较少内存的碎片问题。
3.4.1. 首次适应算法
假设堆中有3块空闲的内存5字节、200字节、100字节pvPortMalloc 想申请 20 字节找出第 1 个能满足 pvPortMalloc 的内存 200 字节把它划分为 20 字节、 180 字节返回这 20 字节的地址剩下的 180 字节仍然是空闲状态留给后续的 pvPortMalloc 使用
Heap_4 会把相邻空闲内存合并为一个大的空闲内存可以较少内存的碎片化问题。适用于这种场景频繁地分配、释放不同大小的内存。 Heap_4 的使用过程举例如下
A创建了 3 个任务B删除了一个任务空闲内存有 2 部分 顶层的被删除任务的 TCB 空间、被删除任务的 Stack 空间合并起来的 C分配了一个 Queue从第 1 个空闲块中分配空间D分配了一个 User 数据从 Queue 之后的空闲块中分配E释放的 Queue User 前后都有一块空闲内存F释放了 User 数据 User 前后的内存、 User 本身占据的内存 合并为一个大的空闲内存 Heap_4 执行的时间是不确定的但是它的效率高于标准库的 malloc、 free。
3.5. Heap_5
Heap_5 分配内存、释放内存的算法跟 Heap_4 是一样的。 相比于 Heap_4 Heap_5 并不局限于管理一个大数组它可以管理多块、分隔开的内存。 在嵌入式系统中内存的地址可能并不连续这种场景下可以使用 Heap_5。 既然内存时分隔开的那么就需要进行初始化确定这些内存块在哪、多大
在使用 pvPortMalloc 之前必须先指定内存块的信息使用 vPortDefineHeapRegions 来指定这些信息
怎么指定一块内存使用如下结构体
typedef struct HeapRegion
{uint8_t * pucStartAddress; // 起始地址size_t xSizeInBytes; // 大小
} HeapRegion_t;怎么指定多块内存使用一个 HeapRegion_t 数组在这个数组中低地址在前、高地址在后。
HeapRegion_t xHeapRegions[]
{{ ( uint8_t * ) 0x80000000UL, 0x10000 }, // 起始地址 0x80000000大小 0x10000{ ( uint8_t * ) 0x90000000UL, 0xa0000 }, // 起始地址 0x90000000大小 0xa0000{ NULL, 0 } // 表示数组结束
};vPortDefineHeapRegions 函数原型如下
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions );把 xHeapRegions 数组传给 vPortDefineHeapRegions 函数即可初始化 Heap_5。
4. Heap接口
4.1. pvPortMalloc/vPortFree
void * pvPortMalloc( size_t xWantedSize );
void vPortFree( void * pv );4.2. xPortGetFreeHeapSize
size_t xPortGetFreeHeapSize( void );只有 heap_4、 heap_5 支持此函数。 4.3. xPortGetMinimumEverFreeHeapSize
size_t xPortGetMinimumEverFreeHeapSize( void );返回程序运行过程中空闲内存容量的最小值 只有 heap_4、 heap_5 支持此函数。 4.4. malloc 失败的钩子函数
void * pvPortMalloc( size_t xWantedSize )vPortDefineHeapRegions