目录
一、概念及其应用
1.1静态内存和动态内存的区别
-
静态内存:程序开始编译时系统自动分配内存空间,包含ZI-Data栈空间、ZI-Data、RW-Data,它们在作用域内使用完毕,系统也会自动释放
-
动态内存:即ZI-Data堆空间,分配在堆区,用户可按需分配
区别:
-
时间不同——静态内存的分配发生在程序编译时,动态内存分配则发生在程序的执行过程
-
空间不同——堆只有动态分配,栈有静态分配和动态分配。,堆的分配和释放用户来完成,栈的两种分配方式都由编译器完成,回收
1.2C标准库动态内存的缺陷
<stdlib.>提供了这些接口:
void *malloc(size_t size) //申请动态内存 返回申请到的内存头指针 万能指针 方便强转
void free(void *ptr) //释放动态内存
void calloc(size_t nmemb, size_t size) //按数组形式申请内存,nmemb是元素个数,size是单个元素的字节数
void *realloc(void *ptr, size_t size) //对于malloc的空间进行扩充申请
缺陷:
-
这些函数在小型嵌入式系统中不总是可用,因为小型嵌入式设备的RAM大小有限
-
它们的函数实现可能非常大,占据了相当大的代码空间
-
线程安全问题
-
根据申请的内存大小不同,每次调用这些函数,执行时间也不一样
-
有可能产生内存碎片,严重影响使用效率
-
使得链接器配置复杂
-
如果允许堆空间的生长方向覆盖其他变量占据的内存,会引起debug灾难
1.3裸机内存分配的痛点
-
没有虚拟内存机制,需要用户亲自管理
-
对内存的分配时间要求苛刻,即分配内存的时间必须确定
-
需要好的内存分配算法
1.4FreeRTOS的动态内存分配
堆栈经常混着说,其实它们不是同一个东西
-
堆,heap,实际就是一块空闲内存,需要使用规定的管理函数来操作,如malloc、free
-
栈,stack,函数调用时局部变量保存在栈中,当前程序的环境也是保存在栈中,特别地,可以从堆中分配一块空间用作栈
FreeRTOS提供了专用的内存管理接口:pvPortMalloc 、vPortFree,对应于C标准库的malloc、free
文件在FreeRTOS/Source/portable/MemMang下,它也是放在portable目录下,表示你可以提供自己的函数。
源码中默认提供了5个文件,对应内存管理的5种方法。
-
heap_1 只实现了pvPortMalloc,没有实现vPortFree,表示只能申请不能释放,当然也就不会产生内存碎片,用于创建后一直使用
-
heap_2 可申请可释放,使用最佳匹配算法(best fit)来分配内存,即会寻找大小最接近需要申请的内存,当然,无法避免内存碎片问题
-
heap_3 可以看作解决了线程安全的malloc、free
-
heap_4 可申请可释放,使用首次适应算法(first fit)来分配内存,即寻找第一块能满足申请要求的内存,同时,他还会把相邻的空闲内存合并为一个更大的空闲内存,这有助于较少内存的碎片问题
-
heap