Chinaunix首页 | 论坛 | 博客
  • 博客访问: 804699
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: 嵌入式

2015-11-24 09:13:27

FreeRTOS内存管理 

       每当创建任务、队列、互斥量、软件定时器或信号量时,RTOS内核会为此分配RAM。标准函数库中的malloc()和free()函数有些时候能够用于完成这个任务,但是…

1.在嵌入式系统中,它们并不总是可以使用的;

2.它们会占用更多宝贵的代码空间;

3.它们没有线程保护;

4.它们不具有确定性(每次调用执行的时间可能会不同);

因此,提供一个替代的内存分配方案通常是必须的。

嵌入式/实时系统具有千差万别的RAM和时间要求,因此一个RAM内存分配算法可能仅属于一个应用的子集。

为了解决这个难题,FreeRTOS在移植层保留内存分配API函数。移植层在RTOS核心 代码源文件之外(不属于核心源代码),这使得不同的应用程序可以提供适合自己的应用实现。当RTOS内核需要RAM时,调用pvPortMallo()函 数来代替malloc()函数。当RAM要被释放时,调用vPortFree()函数来代替free()函数。


RTOS源文件下载包中的内存分配实现

FreeRTOS下载包中提供四种简单的内存分配实现,本章稍后会进行描述。用户可以适当的选择其中的一个,也可以自己设计内存分配。

四种内存分配方案分别在四个源文件(heap_1.c、heap_2.c、heap_3.c 和 heap_4.c)之中,源文件位于下载包FreeRTOSV7.2.0\FreeRTOS\Source\portable\MemMang文件夹中。 其它实现方法可以根据需要增加。这个源文件必须被正确的包含到工程文件中。




heap_1.c

这是一个最简单的实现。一旦分配内存之后,它甚至不允许释放分配的内存。尽管这 样,heap_1.c还是适用于大部分嵌入式应用程序的。这是因为大多数深度嵌入式(deeply embedded)应用只是在系统启动时创建所有任务、队列、信号量等,并且直到程序结束都会一直使用它们,永远不需要删除。

       当需要分配RAM时,这个内存分配方案只是简单的将一个大数组细分出一个子集来。大数组的容量大小通过FreeRTOSConfig.h文件中的configTOTAL_HEAP_SIZE宏来设置。

       API函数xPortGetFreeHeapSize()返回未分配的堆栈空间总大小,可以通过这个函数返回值对configTOTAL_HEAP_SIZE进行合理的设置。

heap_1.c:

(1)用于从不会删除任务、队列、信号量、互斥量等的应用程序(实际上大多数使用FreeRTOS的应用程序都符合这个条件)

(2)执行时间是确定的




heap_2.c

       这个方案使用一个最佳匹配算法,和方案1不同,它允许释放之前分配的内存块。它不会把相邻的空闲块合成一个更大的块(换句话说,这会造成内存碎片)。

       有效的堆栈空间大小由位于FreeRTOSConfig.h文件中的configTOTAL_HEAP_SIZE宏来定义。

       API函数xPortGetFreeHeapSize()返回剩下的未分配堆栈空间的大小(可用于优化设置configTOTAL_HEAP_SIZE宏的值),但是不能提供未分配内存的碎片细节信息。

       heap_2:

l  可以用于重复的分配和删除具有相同堆栈空间的任务、队列、信号量、互斥量等等,并且不必考虑内存碎片的应用程序。

l  不可以用在分配和释放任意字节堆栈空间的应用程序

举例:

?  如果一个应用程序动态的创建和删除任务,并且分配给任务的堆栈空间总是同样大小,那么大多数情况下heap_2.c是可以使用的。但是,如果分配给任务的堆栈不总是相等,那么释放的有效内存可能碎片化,形成很多小的内存块。最后会因为没有足够大的连续堆栈空间而造成内存分配失败。在这种情况下,heap_4.c是一个很好的选择。

?  如果一个应用程序动态的创建和删除队列,并且在每种情况下队列存储区域(队列存储区域指队列项数目乘以每个队列长度)都是同样的,那么大多数情况下 heap_2.c可以使用。但是,如果队列存储区在每种情况下并不总是相等,那么释放的有效内存可能碎片化,形成很多小的内存块。最后会因为没有足够大的 连续堆栈空间而造成内存分配失败。在这种情况下,heap_4.c是一个很好的选择。

?  应用程序应该直接调用pvPortMalloc() 和 vPortFree()函数,而不是通过FreeRTOS间接调用。

l  如果你的应用程序中的队列、任务、信号量、互斥量等等处在一个不可预料的状态,则可能会导致内存碎片问题,必须牢记。

l  不具有确定性,但是它比标准库中的malloc函数具有高得多的效率。

heap_2.c适用于需要动态创建任务的大多数小型实时系统(small real time)。




heap_3.c

       heap_3.c简单的包装了标准库中的malloc()和free()函数,包装后的malloc()和free()函数具备线程保护。

heap_3.c:

l  需要链接器设置一个堆栈,并且编译器库提供malloc()和free()函数。

l  不具有确定性

l  可能明显的增大RTOS内核的代码大小

注:使用heap_3时,FreeRTOSConfig.h文件中的configTOTAL_HEAP_SIZE宏定义没有作用。




heap_4.c

       这个方案使用一个最佳匹配算法,但不像方案2那样。它会将相邻的空闲内存块合并成一个更大的块(包含一个合并算法)。

       有效的堆栈空间大小由位于FreeRTOSConfig.h文件中的configTOTAL_HEAP_SIZE来定义。

       API函数xPortGetFreeHeapSize()返回剩下的未分配堆栈空间的大小(可用于优化设置configTOTAL_HEAP_SIZE宏的值),但是不能提供未分配内存的碎片细节信息。

heap_4.c:

l  可用于重复的分配和删除具有相同堆栈空间的任务、队列、信号量、互斥量等等的应用程序。

l  可以用于分配和释放任意字节内存的情况

l  不具有确定性,但是它比标准库中的malloc函数具有高得多的效率。

heap_4.c特别适用于在应用代码中可直接使用移植层内存分配方案的应用程序。

阅读(2438) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~