堆内存管理

2019-10-13 07:08栏目:www.qy66.vip
TAG:

因为品种需求,这两天最早学习FreeRTOS,一开端有些打鼓,因为多个礼拜在此以前对于FreeRTOS的熟习度差非常的少为零,经过对FreeRTOS官方网址的事例程序的查找,和花色中难点的化解,蒙受了重重熟知的人影,曾在Linux平台编制程序的阅历给了本人有些卓越立见成效的经历,后悔当初没能在率先家公司待下去,浪费了大好时光。可以吗,今后仍旧潜下心来搞搞FreeRTOS吧。

后续都以一多种FreeRTOS相关的小说,先把FreeRTOS“圣经”--Mastering the FreeRTOS Real Time kernel -- A Hands On Tutorial Guide 20161204美貌研读,接连的多少个小说都以自个儿从那本“圣经”中翻译出来的。翻译难免存有疏漏、词不达意,大家凑合着看吗。

从FreeRTOS V9.0.0起来FreeRTOS应用程序能够完全用静态分配内部存款和储蓄器,而从不须要引进堆内部存款和储蓄器管理。

章节引言和限量

前提

FreeRTOS是以C源文件的款式提供的,因而产生一名合格的C语言编制程序人士是应用FreeRTOS的须要条件,因此那一个章节日假日定读者熟习以下概念:

  • C语言项目是什么营造的,包涵分化的编写翻译和链接进程
  • 堆和栈分别是如何
  • 标准C库的malloc()free()函数

动态内存分配以致它和FreeRTOS的涉及

从FreeRTOS V9.0.0起来根本对象不仅可以够在编写翻译的时候静态分配,也能够在运维时动态分配。本书随后的章节将会介绍以下基本对象:tasks, queues, semaphoresevent groups。为了尽量让FreeRTOS易于使用,那几个根本对象并不是在编写翻译时静态分配的,而是在运转时动态分配的。内核查象创立时FreeRTOS分配RAM而在根本对象删除时释放内部存款和储蓄器。那样的计谋缩小了规划和布置上的努力,简化了API,並且减少了RAM的占用。

动态内部存款和储蓄器分配是C语言编制程序的定义,并不是针对性FreeRTOS或许多任务编制程序的概念。它和FreeRTOS是相关的,因为基本对象是动态分配的,並且通用编写翻译器提供的动态内部存款和储蓄器分配方案对于实时应用程序并不接二连三切合的。

内部存款和储蓄器能够选择正规C库的malloc()free()函数来分配,但有望不相符,或然适度,因为下几点原因:

  • 在Mini嵌入式系统中并不一连可用的
  • 它们的兑现也许非常的大,攻陷了一对一大的一块代码空间
  • 她们差不离都不是线程安全的
  • 它们并非明确的,每一遍调用那个函数试行的小运可能都不平等
  • 它们有望爆发碎片
  • 它们有不小希望打乱链接器的配置
  • 若是允许堆空间的生长方向覆盖任何变量私吞的内部存款和储蓄器,它们会化为debug的灾难

动态内部存款和储蓄器分配的可选项

从FreeRTOS V9.0.0始发根本对象不只能够在编写翻译时静态分配也得以在运作时动态分配。这段日子FreeRTOS把内部存款和储蓄器分配放在可移植层。那是认知到不相同的嵌入式操作有例外的动态内部存款和储蓄器管理章程和岁月供给,由此单个的动态内部存款和储蓄器分配算法将只切合于应用程序的贰个子集。同样,从着力代码库中移除动态内部存款和储蓄器分配使得应用程序编写者提供本身的特定的完毕,如若切合的话。

当FreeRTOS要求RAM的时候,并非调用malloc(),而是调用pvPortMalloc()。当供给自由RAM的时候,而不是调用free(),而是调用vPortFree()pvPortMalloc()和标准C库的malloc()有一致的函数原型,vPortFree()和标准C库的free()有同样的函数原型。

pvPortMalloc()vPortFree()都是公共函数,由此能够被应用代码调用。

FreeRTOS对于pvPortMalloc()vPortFree()提供了5种达成,后续章节会讲到。FreeRTOS应用程序可以选择当中的一种,可能采纳自个儿的达成。5种实现各自在heap_1.c, heap_2.c, heap_3.c, heap_4.cheap_5.c文本中,都留存于文件夹 FreeRTOS/Source/portable/MemMang 下。

范围

本章节转业于让读者浓烈掌握:

  • FreeRTOS哪天分配RAM
  • FreeRTOS 提供的5种内部存储器分配方案
  • 选拔哪一类内部存储器分配方案

内存分配方案示例

Heap_4 (其余两种暂不去询问)

heap_1, heap_2 一样,heap_4也是把数组切割成更加小的块。和前边一样,数组是静态申明的,由宏configTOTAL_HEAP_SIZE钦命大小,所以那就使得就算数组中的内部存款和储蓄器还不曾被分配出去就让应用程序显得消耗了一大波的RAM。

Heap_4动用了第一适应算法来分配内存。和heap_2不同,heap_4把贴近的悠闲的仓库储存空间拼凑成二个越来越大的内部存款和储蓄器块,那就减弱了内部存储器碎片化的高危害。

首先适应算法确定保障了pvPortMalloc()使用第一块空闲的十足大的内部存款和储蓄器来知足要申请的字节数。思考上边包车型地铁景色:

  • 堆里有3块空闲内存块,它们的轻重缓急分别是5个字节,200个字节,九拾伍个字节
  • 调用pvPortMalloc()来报名十多少个字节的RAM
    满意字节数必要的率先块空闲RAM块是200个字节的RAM块,因而pvPortMalloc()把大小为200个字节的RAM块分割成两块,一块是十八个字节,一块是1八十几个字节,然会再次来到多个对准十八个字节的指针。新的1柒17个字节大小的RAM块就要承袭的pvPortMalloc()调用中可用。

Figure 7 演示了 heap_4 最早适应算法如何拼接内部存款和储蓄器,同样也演示了内部存款和储蓄器的分红和释放:

图片 1

  1. A示范了创办3个职分之后的数组的标准,一大块空的块存在于数组的下边。
  2. B示范了删除1个职责之后的数组,一大块空的块存在于数组的上方。被去除的特别职责攻下的TCB和栈存款和储蓄空间未来是空的,並且它们拼接成贰个大的空的块。
  3. C演示了FreeRTOS创设了八个Queue。队列是经过xQueueCreate() API 成立的,它是调用pvPortMalloc() 来分配存款和储蓄空间的。由于heap_4运用最初适应算法,pvportMalloc()将会使用第一块大的丰盛容纳队列的RAM块来分配,在Figure 7中就应用从前删除职责的那一块。不过队列并不完全消耗这个空闲的区块,所以那么些RAM块会分成八个部分,未采用的一部分将会由持续的pvPortMalloc()占用。
  4. D演示了应用程序直接调用pvPortMalloc()实际不是直接地由FreeRTOS API调用之后的情事。客户分配的区块丰富小,能够放在第一个空闲的区块中,这几个区块正是队列占用的区块和前面的TCB占用的区块之间的那一块。
    删除任务释放的内部存款和储蓄器,未来被划分成3个区块,第一个区块是队列,第4个区块是客商分配的,第多个区块依然空的。
  5. E 演示了队列删除之后,存款和储蓄空间也自行释放了。以后客商分配的区块两侧都以空闲区块。
  6. F 演示了客商分配的存放空间释放的情景。那个区块以往和两侧的空闲区块拼接成了八个越来越大的空闲区块。

Heap_4而不是深入人心的,不过要比规范库函数完结的malloc()free()运维的越来越快。

设定Heap_4数组的前奏地址

此章节带有更加高阶的消息,仅仅为了利用Heap_4是绝非要求阅读和清楚此章节的。

一点时候应用程序开辟者要求内定heap_4数组的开场面址位于有些特定的内部存储器。比如,FreeRTOS 职分的栈是从堆中分配的,就有十分大希望有须求保证堆是分配在高速的内部存储器中,并不是慢速的外存。

暗中同意意况下,heap_4数组是在heap_4.c源文件中评释的,它的开始地址是由链接器自动分明的。可是,尽管在文件FreeRTOSConfig.h中把编写翻译时布置选项configAPPLICATION_ALLOCATED_HEAP设为常量1,那么数组必需由运用FreeRTOS的利用评释。借使把数组证明为运用的一部分,那么应用编写者能够钦赐数组的发端地址。

设若把公文FreeRTOSConfig.h中的configAPPLICATION_ALLOCATED_HEAP设定为1,那么应用程序源文件中必得声美赞臣(Meadjohnson)个名称为ucHeapuint8_t花色的数组,它的高低有configTOTAL_HEAP_SIZE设定。

把变量放在某些内部存款和储蓄器地址的语法决计于使用了哪类编写翻译器,下边演示了二种编译器的用法:

  1. Listing 2演示的是GCC编写翻译器注脚数组并把数组放在名称为.my_heap的段中。
  2. Listing 3演示的是IA中华V编写翻译器把数组放在内部存款和储蓄器相对地址0x20000000上。

uint8_t ucHeap [configTOTAL_HEAP_SIZE] attribute (( section(".my_heap") ));

Listing 2

uint8_t ucHeap [configTOTAL_HEAP_SIZE] @ 0x20000000;

Listing 3

和堆相关的实用函数

xPortGetFreeHeapSize() API

这些函数能够获取调用时堆中空闲内部存款和储蓄器的轻重缓急,以字节为单位。使用它能够优化堆的大大小小。比方,当内核对象都创制完成后调用xPortGetFreeHeapSize()归来3000,那么能够把configTOTAL_HEAP_SIZE减小2000.

内需留意,当使用heap_3时是不能够调用那几个函数的。

xPortGetMinimumEverFreeHeapSize() API

此函数重返FreeRTOS应用程序起首运转之后一度存在的小不点儿的未被分配的存放空间的字节数。它的再次来到值提示了应用程序离将在耗尽堆空间的类似程度。举例xPortGetMinimunEverFreeHeapSize()归来200个字节,那么从应用程序最早运营之后的有个别时刻,在选用200个字节就可以把堆空间用完。

亟需小心,xPortGetMinimumEverFreeHeapSize()只在使用heap_4或者heap_5时生效。

Malloc 失利钩子函数

应用程序能够平昔调用pvPortMalloc()。当然在FreeRTOS源文件中每当内核查象创制时也会调用那几个函数。此类的根本对象富含职务,队列,非数字信号量和事件组。

和正式库函数malloc()一样,如果pvPortMalloc()因为申请RAM的轻重缓急不可能满意未能重返一块RAM空间就能够回到NULL。就算编程人士调用pvPortMalloc()来创立基础对象,可是回到NULL就认证内核查象未有开创成功。

事例中的全体堆分配方案都能够给pvPortMalloc()布置二个钩子函数(也称作回调函数),当pvPortMalloc()返回NULL时调用那个钩子函数。

固然文件FreeRTOSConfig.h中的configUSE_MALLOC_FAILED_HOOK设置为1,那么应用程序必需提供八个内部存储器分配失利时的钩函数,它的名字和原型参见如下。只要对这几个应用来讲是妥帖的,这一个钩子函数能够用任何格局来贯彻。

void vApplicationMallocFailedHook( void );

声明

招待转发,请评释出处和小编,同一时候保留注解。
作者:LinTeX9527
出处:
本博客的篇章如无特殊表明,均为原创,转发请注解出处。如未经小编同意必得保留此段申明,且在篇章页面明显地点给出原著连接,不然保留追究法律义务的义务。

版权声明:本文由千亿游戏官网发布于www.qy66.vip,转载请注明出处:堆内存管理