C语言Free途乐TOS–堆内部存款和储蓄器管理

因为品种需求,方今伊始上学Free福特ExplorerTOS,一发轫有点忐忑,因为八个礼拜从前对于Free奥迪Q3TOS的纯熟度大概为零,经过对Free纳瓦拉TOS官网的例子程序的探寻,和花色中难题的缓解,碰着了累累熟练的身影,此前在Linux平台编制程序的经历给了自家有的优良实惠的经验,后悔当初没能在第壹家店铺待下去,浪费了大好时光。好呢,现在依旧潜下心来搞搞Free劲客TOS吧。

一而再都是一层层Free奥迪Q5TOS相关的小说,先把FreeRTOS“圣经”Mastering the FreeRTOS Real Time kernel -- A Hands On Tutorial Guide 20161204好好研读,接连的多少个小说都以笔者从这本“圣经”中翻译出来的。翻译难免存有疏漏、词不达意,大家凑合着看呢。

从Free本田UR-VTOS
V9.0.0开端FreeKugaTOS应用程序能够完全用静态分配内部存储器,而从未须求引入堆内部存储器管理。

章节引言和限制

前提

Free帕杰罗TOS是以C源文件的款型提供的,因而成为一名合格的C语言编程职员是行使Free卡宴TOS的须求条件,因此那一个章节日假期定读者熟识以下概念:

  • C语言项目是何许营造的,包涵差别的编写翻译和链接进度
  • 堆和栈分别是哪些
  • 标准C库的malloc()free()函数

动态内部存款和储蓄器分配以及它和FreeSportageTOS的关系

从Free路虎极光TOS
V9.0.0方始根本对象既能够在编写翻译的时候静态分配,也能够在运维时动态分配。
本书随后的章节将会介绍以下基本对象:tasks,
queues, semaphoresevent
groups
。为了尽大概让Free奇骏TOS易于使用,那一个根本对象并不是在编写翻译时静态分配的,而是在运营时动态分配的。内核对象创造时FreePRADOTOS分配RAM而在基础对象删除时释放内部存款和储蓄器。那样的策略收缩了统筹和布置上的着力,简化了API,并且收缩了RAM的占用。

动态内部存款和储蓄器分配是C语言编制程序的定义,而不是对准Free奥迪Q7TOS或许多任务编制程序的概念。它和FreeEvoqueTOS是连锁的,因为根本对象是动态分配的,并且通用编写翻译器提供的动态内部存款和储蓄器分配方案对于实时应用程序并不总是适合的。

内部存款和储蓄器能够利用规范C库的malloc()free()函数来分配,但有大概不吻合,恐怕适度,因为下几点原因:

  • 在小型嵌入式系统中并不总是可用的
  • 它们的落到实处恐怕那一个的大,占据了一对一大的一块代码空间
  • 她俩大概都不是线程安全的
  • 它们并不是规定的,每一趟调用那么些函数执行的小运大概都分化
  • 它们有大概产生碎片
  • 它们有只怕打乱链接器的布局
  • 假设同意堆空间的生长方向覆盖任何变量占据的内部存款和储蓄器,它们会化为debug的灾难

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

从Free福睿斯TOS
V9.0.0方始根本对象既能够在编写翻译时静态分配也得以在运转时动态分配
。最近FreeWranglerTOS把内部存款和储蓄器分配放在可移植层。那是认识到不相同的嵌入式操作有两样的动态内部存款和储蓄器管理格局和岁月须要,因而单个的动态内部存款和储蓄器分配算法将只适合于应用程序的贰个子集。同样,从基本代码库中移除动态内部存款和储蓄器分配使得应用程序编写者提供本身的特定的贯彻,就算符合的话。

当Free本田CR-VTOS须要RAM的时候,并不是调用malloc(),而是调用pvPortMalloc()。当供给释放RAM的时候,并不是调用free(),而是调用vPortFree()pvPortMalloc()和标准C库的malloc()有一致的函数原型,vPortFree()和标准C库的free()有平等的函数原型。

pvPortMalloc()vPortFree()都是共用函数,因而能够被使用代码调用。

FreeRTOS对于pvPortMalloc()vPortFree()提供了5种实现,后续章节会讲到。Free揽胜TOS应用程序能够动用其中的一种,只怕选取本身的落到实处。5种完结各自在heap_1.c,
heap_2.c, heap_3.c, heap_4.cheap_5.c文件中,都存在于文件夹
FreeRTOS/Source/portable/MemMang 下。

范围

本章节从业于让读者长远通晓:

  • Free途达TOS曾几何时分配RAM
  • Free景逸SUVTOS 提供的5种内部存款和储蓄器分配方案
  • 选择哪类内部存款和储蓄器分配方案

内部存款和储蓄器分配方案示例

Heap_4 (别的三种暂不去精通)

heap_1, heap_2
一样,heap_4也是把数组切割成更小的块。和后边一样,数组是静态注解的,由宏configTOTAL_HEAP_SIZE点名大小,所以那就使得尽管数组中的内部存款和储蓄器还一向不被分配出去就让应用程序显得消耗了大量的RAM。

Heap_4利用了第三适应算法来分配内部存款和储蓄器。和heap_2不同,heap_4把贴近的悠闲的贮存空间拼凑成三个更大的内部存款和储蓄器块,那就收缩了内部存款和储蓄器碎片化的高风险。

首先适应算法确认保障了pvPortMalloc()运用第3块空闲的丰盛大的内部存储器来满足要提请的字节数。考虑上边包车型的士现象:

  • 堆里有3块空闲内部存款和储蓄器块,它们的尺寸分别是四个字节,200个字节,九十几个字节
  • 调用pvPortMalloc()来报名1几个字节的RAM
    满意字节数须求的率先块空闲RAM块是200个字节的RAM块,因而pvPortMalloc()把大小为200个字节的RAM块分割成两块,一块是十7个字节,一块是1七十六个字节,然会重临三个对准十八个字节的指针。新的1七十七个字节大小的RAM块将在继承的pvPortMalloc()调用中可用。

Figure 7 演示了 heap_4
发轫适应算法怎样拼接内部存款和储蓄器,同样也演示了内部存款和储蓄器的分配和刑释:

C语言 1

  1. A以身作则了创设一个职分之后的数组的典范,一大块空的块存在于数组的下边。
  2. B以身作则了剔除二个职务之后的数组,一大块空的块存在于数组的下面。被剔除的不胜任务占据的TCB和栈存款和储蓄空间现在是空的,并且它们拼接成多少个大的空的块。
  3. C以身作则了FreeLX570TOS创设了3个Queue。队列是透过xQueueCreate() API
    成立的,它是调用pvPortMalloc()
    来分配存款和储蓄空间的。由于heap_4使用开头适应算法,pvportMalloc()将会动用第③块大的丰裕容纳队列的RAM块来分配,在Figure
    7中就应用此前删除职务的那一块。可是队列并不完全消耗那些空闲的区块,所以尤其RAM块会分成四个部分,未利用的部分将会由持续的pvPortMalloc()占用。
  4. D以身作则了应用程序直接调用pvPortMalloc()而不是直接地由FreeHighlanderTOS
    API调用之后的情事。用户分配的区块丰硕小,能够放在第2个空闲的区块中,那几个区块就是队列占用的区块和前面包车型客车TCB占用的区块之间的那一块。
    剔除任务释放的内部存款和储蓄器,以往被分割成一个区块,第3个区块是队列,首个区块是用户分配的,第四个区块仍旧空的。
  5. E
    演示了队列删除之后,存款和储蓄空间也自动释放了。将来用户分配的区块两边都以空闲区块。
  6. F
    演示了用户分配的储存空间释放的情况。那个区块未来和两边的空闲区块拼接成了三个更大的空闲区块。

Heap_4并不是明显的,不过要比标准库函数完成的malloc()free()运作的更快。

设定Heap_4数组的序幕地址

此章节带有更高阶的消息,仅仅为了利用Heap_4是一直不必要阅读和精通此章节的。

好何时候应用程序开发者要求钦定heap_4数组的苗子地址位于有个别特定的内部存款和储蓄器。例如,Free卡宴TOS
义务的栈是从堆中分红的,就有大概有必不可少有限支撑堆是分配在急迅的内部存款和储蓄器中,而不是慢速的外部存款和储蓄器。

暗中同意情状下,heap_4数组是在heap_4.c源文件中宣称的,它的发端地址是由链接器自动明确的。可是,假诺在文书FreeRTOSConfig.h中把编写翻译时计划选项configAPPLICATION_ALLOCATED_HEAP设为常量1,那么数组必须由使用FreeTiggoTOS的行使注明。尽管把数组注脚为利用的一部分,那么应用编写者能够钦点数组的前奏地址。

假若把公文FreeRTOSConfig.h中的configAPPLICATION_ALLOCATED_HEAP设定为1,那么应用程序源文件中务必声雅培个名字为ucHeapuint8_t项目标数组,它的分寸有configTOTAL_HEAP_SIZE设定。

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

  1. Listing
    2演示的是GCC编写翻译器注脚数组并把数组放在名字为.my_heap的段中。
  2. Listing 3演示的是IAEnclave编写翻译器把数组放在内部存款和储蓄器相对地址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

此函数再次回到FreeHavalTOS应用程序早先运维之后一度存在的细微的未被分配的存款和储蓄空间的字节数。它的重临值提醒了应用程序离将要耗尽堆空间的好像程度。例如xPortGetMinimunEverFreeHeapSize()回来200个字节,那么从应用程序开端运营之后的有个别时间,在利用200个字节就会把堆空间用完。

亟需留意,xPortGetMinimumEverFreeHeapSize()只在动用heap_4或者heap_5时生效。

Malloc 退步钩子函数

应用程序能够一直调用pvPortMalloc()。当然在Free汉兰达TOS源文件中每当内查对象创立时也会调用那几个函数。此类的木本对象包含职责,队列,信号量和事件组。

和专业库函数malloc()一样,如果pvPortMalloc()因为申请RAM的深浅不能够满足没能再次来到一块RAM空间就会回到NULL。借使编制程序职员调用pvPortMalloc()来成立基础对象,不过回到NULL就证实内核对象没有成立成功。

事例中的全部堆分配方案都得以给pvPortMalloc()计划2个钩子函数(也称作回调函数),当pvPortMalloc()返回NULL时调用这些钩子函数。

比方文件FreeRTOSConfig.h中的configUSE_MALLOC_FAILED_HOOK设置为1,那么应用程序必须提供贰个内部存款和储蓄器分配失利时的钩函数,它的名字和原型参见如下。只要对这一个应用来说是恰如其分的,那个钩子函数能够用其余措施来贯彻。

void vApplicationMallocFailedHook( void );

声明

欢迎转发,请注脚出处和小编,同时保留证明。
作者:LinTeX9527
出处:http://www.cnblogs.com/LinTeX9527/p/8007541.html
本博客的小说如无特殊表达,均为原创,转发请声明出处。如未经作者同意必须保留此段证明,且在小说页面明显地点给出原作连接,不然保留追究法律义务的权利。