抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

内存管理

内存通常分为两种:内部存储空间(RAM​)和外部存储空间(硬盘)

避免使用C​语言标准库的malloc​和free​内存函数

  1. 嵌入式RAM​可能不足,函数并不总是可用
  2. 实现可能很大,占用很大的代码空间
  3. 几乎不安全
  4. 调用时间不确定,每次可能都不一样
  5. 可能产生碎片
  6. 会使链接器配置复杂
  7. 如果允许堆空间的生长方向覆盖其他变量占据的内存,会成为debug​的灾难

内存管理应用场景

  1. void *pvPortMalloc(size_t xSize)​申请内存
  2. void vPortFree(void *pv)​释放内存
  3. void vPortInitialiseBlocks(void)​初始化内存堆
  4. size_t xPortGetFreeHeapSize(void)​获取当前未分配的内存堆大小
  5. size_t xPortGetMinimumEverFreeHeapSize(void)​获取未分配的内存堆历史最小值
  6. heap_1.c​、heap_2.c​、heap_4.c​内存堆是一个很大的数组
  7. heap_3.c​是使用C​语言原生的malloc​和free​函数,但是进行的安全保护的封装,需要用户通过编译器或者启动文件设置空间
  8. heap_5.c​允许用户使用多个非连续的内存堆空间,同时可以使用外部SDRAM、内存卡等

heap_1

  1. 用于从不删除任务、队列、信号量、互斥量等应用程序
  2. 函数执行时间是确定并且不会产生内存碎片
  3. 不支持释放内存

heap_2

  1. heap_1​的内存管理算法不同,采用最佳匹配算法,支持释放内存不能将相邻的小碎片内存合并为大内存
  2. 可用于反复删除任务、队列、信号量、互斥量等内核对象且不担心内存碎片的应用程序
  3. 若存在一些碎片化的任务,那么可能导致内存碎片
  4. 具有不确定性,但是比C​语言原生的malloc​高级
  5. 不能用于内存分配和释放是随机大小的应用程序

heap_3

  1. 简单封装C​语言的malloc​和free​,满足常用的编译器,具有保护功能
  2. 需要链接器设置一个堆,malloc​和free​由编译器提供
  3. 具有不确定性
  4. 很可能增大RTOS​内核代码大小
  5. configTOTAL_HEAP_SIZE​宏定义不起作用

heap_4

  1. heap_2​的基础上加上了合并算法,能将相邻空闲内存合并为1个更大的块
  2. 可用于重复删除任务、队列、信号量、互斥量等的应用程序
  3. 可用于分配和释放随机字节内存的应用程序,但并不像heap_2​那样产生严重的内存碎片
  4. 具有不确定性,但是效率比C​语言原生的malloc​函数高

heap_5

  1. 动态分配和heap_4​是一样,采用最佳匹配和合并算法,并且允许内存跨多个非连续内存区
  2. 需要使用vPortDefineHeapRegions()​来实现内存初始化

创建内存管理

内存管理句柄,创建一个引用,并不是创建一个真实的内存管理

1
2
3
4
//内存管理
static TaskHandle_t Test_Task_Handle=NULL;

uint8_t *Test_Ptr=NULL;

Test任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//内存管理
static void Test_Task(void *paramter)
{
uint32_t g_memsize;
while (1)
{
if (Key_BTN(BTN1)==KEY_ON)
{
if (Test_Ptr==NULL)
{
//获取当前内存大小
g_memsize=xPortGetFreeHeapSize();
printf("系统当前内存大小为%d字节,开始申请内存\r\n",g_memsize);
Test_Ptr = pvPortMalloc(1024);
if (Test_Ptr!=NULL)
{
printf("内存申请成功\r\n");
printf("申请到的内存地址为%#x\r\n",(int)Test_Ptr);
// 当前剩余内存大小
g_memsize = xPortGetFreeHeapSize();
printf("系统当前内存剩余大小为%d字节\r\n",g_memsize);

sprintf((char*)Test_Ptr,"当前系统TickCount=%d\r\n",xTaskGetTickCount);
printf("写入数据是%s\r\n",(char*)Test_Ptr);
}else
{
printf("按下Key2释放内存然后申请\r\n");
}
}
}
if (Key_BTN(BTN2)==KEY_ON)
{
if (Test_Ptr!=NULL)
{
printf("释放内存\r\n");
vPortFree(Test_Ptr);
Test_Ptr=NULL;
// 获取当前剩余内存
g_memsize = xPortGetFreeHeapSize();
printf("系统当前内存剩余大小为%d字节\r\n",g_memsize);
}else
{
printf("按下Key1申请内存再释放\r\n");
}

}
vTaskDelay(20);
}
}

按下BTN1​申请内存,并将系统当前TickCount​打印,按下BTN2​释放内存