1.前言

不同的嵌入式系统具有不同的内存配置和时间要求。所以单一的内存分配算法只可能适合部分应用程序。

FreeRTOS 将内存分配作为可移植层面(相对于基本的内核代码部分而言)。这使得不同的应用程序可以提供适合自身的具体实现。

本章期望让读者了解以下事情:

  • FreeRTOS 在什么时候分配内存。
  • FreeRTOS 提供的三种内存分配方案范例

2.FreeRTOS内存管理概述

(1)当内核请求内存时,其调用pvPortMalloc()而不是直接调用malloc();当释放内存时,调用vPortFree()而不是直接调用free()。

pvPortMalloc()具有与malloc()相同的函数原型;vPortFree()也具有与free()相同的函数原型。

(2)FreeRTOS 自带有三种pvPortMalloc()与vPortFree()实现范例.FreeRTOS 的用户可以选用其中一种,也可以采用自己的内存管理方式

这三个范例对应三个源文件:heap_1.c,heap_2.c,heap_3.c——这三个文件都放在目录FreeRTOS\Source\Portable\MemMang 中

(3)早期版本的FreeRTOS 所采用的原始内存池和内存块分配方案已经被移除了,因为定义内存块和内存池的大小需要较深入的努力和理解。

(4)选择内存分配方案时不必考虑一些复杂的因素,比如确定性与内存碎片等,而只需要从性能上考虑,比如代码大小和简易性

在小型嵌入式系统中,通常是在启动调度器之前创建任务,队列和信号量。

这种情况表明,动态分配内存只会出现在应用程序真正开始执行实时功能之前,而且内存一旦分配就不会再释放

3. 内存分配方案范例

3.1 heap_1.c原理说明

(1)Heap_1.c 实现了一个非常基本的pvPortMalloc()版本,而且没有实现vPortFree()
如果应用程序不需要删除任务,队列或者信号量,则具有使用heap_1 的潜质

(2)这种分配方案是将FreeRTOS 的内存堆空间看作一个简单的数组。

当调用pvPortMalloc()时,则将数组又简单地细分为更小的内存块。

(3)数组的总大小(字节为单位)在FreeRTOSConfig.h 中由configTOTAL_HEAP_SIZE定义。

以这种方式定义一个巨型数组会让整个应用程序看起来耗费了许多内存——即使是在数组没有进行任何实际分配之前。

(4)需要为每个创建的任务在堆空间上分配一个任务控制块(TCB)和一个栈空间

3.2 heap_1.c内存分配示例

(1)A 表示数组在没有任何任务创建时的情形,这里整个数据是空的。

(2)B 表示数组在创建了一个任务后的情形。

(3)C 表示数组在创建了三个任务后的情形。

3.3 heap_2.c原理说明

(1)Heap_2.c 也是使用了一个由configTOTAL_HEAP_SIZE 定义大小的简单数组

(2)不同于heap_1 的是,heap_2 采用了一个最佳匹配算法来分配内存,并且支持内存释放

(3)由于声明了一个静态数组,所以会让整个应用程序看起来耗费了许多内存——即使是在数组没有进行任何实际分配之前

(4)最佳匹配算法保证pvPortMalloc()会使用最接近请求大小的空闲内存块

举例:堆空间中包含了三个空闲内存块,分别为5 字节,25 字节和100 字节大小。pvPortMalloc()被调用以请求分配20 字节大小的内存空间。

匹配请求字节数的最小空闲内存块是具有25字节大小的内存块——所以pvPortMalloc()会将这个25 字节块再分为一个20 字节块和一个5 字节块3,然后返回一个指向20 字节块的指针。

剩下的5 字节块则保留下来,留待以后调用pvPortMalloc()时使用

(5)Heap_2.c 并不会把相邻的空闲块合并成一个更大的内存块,所以会产生内存碎片——如果分配和释放的总是相同大小的内存块,则内存碎片就不会成为一个问题

(6)Heap_2.c 适合用于那些重复创建与删除具有相同栈空间任务的应用程序

3.4 heap_2.c内存分配示例

上图展示了当任务创建,删除以及再创建过程中,最佳匹配算法是如何工作的

(1)A 表示数组在创建了三个任务后的情形。数组的顶部还剩余一个大空闲块。

(2) B 表示数组在删除了一个任务后的情形。顶部的大空闲块保持不变,并多出了两个小的空闲块,分别是被删除任务的TCB 和任务栈。

(3) C 表示数组在又创建了一个任务后的情形。创建一个任务会产生两次调用pvPortMalloc(),一次是分配TCB,一次是分配任务栈

注:(1)调用pvPortMalloc()发生在xTaskCreate() API 函数内部

(2)每个TCB 都具有相同大小,所以最佳匹配算法可以确保之前被删除的任务占用的TCB 空间被重新分配用作新任务的TCB 空间。

(3)新建任务的栈空间与之前被删除任务的栈空间大小相同,所以最佳匹配算法会保证之前被删除任务占用的栈空间会被重新分配用作新任务的栈空间。数组顶部的大空闲块依然保持不变。

(4)Heap_2.c 虽然不具备确定性,但是比大多数标准库实现的malloc()与free()更有效率

3.5 heap_3.c原理说明

(1)Heap_3.c 简单地调用了标准库函数malloc()和free(),但是通过暂时挂起调度器使得函数调用具备线程安全特性

(2)内存堆空间大小不受configTOTAL_HEAP_SIZE 影响,而是由链接器配置

3.6 heap_3.c内存分配举例

4.参考文献

[1]FreeRTOS中文实用教程

freeRTOS中文实用教程5--内存管理的更多相关文章

  1. freeRTOS中文实用教程4--资源管理互斥

    1.前言 访问一个被多任务共享,或是被任务与中断共享的资源时,需要采用”互斥”技术以保证数据在任何时候都保持一致性.这样做的目的是要确保任务从开始访问资源就具有排它性,直至这个资源又恢复到完整状态 F ...

  2. freeRTOS中文实用教程4--资源管理概述

    1.前言 多任务系统中存在一种潜在的风险.当一个任务在使用某个资源的过程中,即还没有完全结束对资源的访问时,便被切出运行态,使得资源处于非一致,不完整的状态 2.并发抢占导致错误的场景 (1)访问外设 ...

  3. freeRTOS中文实用教程3--中断管理之中断嵌套

    1.前言 最新的 FreeRTOS 移植中允许中断嵌套.中断嵌套需要在 FreeRTOSConfig.h 中设置configKERNEL_INTERRUPT_PRIORITY 和configMAX_S ...

  4. freeRTOS中文实用教程3--中断管理之计数信号量

    1.前言 在中断不频繁的系统中,使用二值信号量没有问题,但是中断频繁发生时,则会有中断丢失的问题. 因为中断发生时延迟任务执行,延迟任务执行的过程中,如果又来了两次中断,则只会处理第一次,第二次将会丢 ...

  5. freeRTOS中文实用教程3--中断管理之中断服务例程中使用队列

    1.前言 消息队列不仅可以用于事件通信,还可以用来传递数据 2.实例说明消息队列的执行过程 3.主要API API名称 说明 参数 返回值 xQueueSendFromISR()完全等同于 xQueu ...

  6. freeRTOS中文实用教程3--中断管理之延迟中断处理

    1.前言 嵌入式实时操作系统需要对整个系统环境产生的事件作出响应.可以采用中断方式也可以采用轮询方式来进行处理.如果采用中断方式,则希望ISR(中断服务例程)的处理时间越短越好. 注:必须说明的是,只 ...

  7. freeRTOS中文实用教程6--错误排查

    1.前言 本章主要是为刚接触FreeRTOS 的用户指出那些新手通常容易遇到的问题.这里把最主要的篇幅放在栈溢出以及栈溢出侦测上 2.printf-stdarg.c 当调用标准C 库函数时,栈空间使用 ...

  8. freeRTOS中文实用教程1--任务

    1.前言 FreeRTOS是小型多任务嵌入式操作系统,硬实时性.本章主要讲述任务相关特性及调度相关的知识. 2. 任务的总体特点 任务的状态 (1)任务有两个状态,运行态和非运行态 (2)任务由非运行 ...

  9. freeRTOS中文实用教程2--队列

    1.前言 freeRTOS中所有任务的通信和同步机制都是基于队列来实现. 2.队列的特点 图 队列的读写操作 队列的数据存储 (1)队列可以保存有限个具有确定长度的数据单元,队列可以保存的最大单元数目 ...

随机推荐

  1. pdo连接的时候设置字符编码是这样的

    $pdo = new \PDO(..,..,..) $pdo->query('SET NAMES utf8mb4'); $pdo->exex('sql....');

  2. 丢手帕问题 (约瑟夫问题)Java实现

    问题: 丢手帕游戏是约瑟夫问题的一个变种,游戏很简单,N个小孩围成一个圈,标号为1到N,从编号为m的小孩开始报数,报到第L个小孩退出游戏,然后下一个小孩继续从1开始报数,数到第L个小孩退出游戏,如此循 ...

  3. A1075. PAT Judge

    The ranklist of PAT is generated from the status list, which shows the scores of the submittions. Th ...

  4. vue实现添加与删除图书

    先放大图,当我们点击删除的时候,图书名单就会被我们删掉.当我们重新添加回来或者添加新书的时候,我们只需要在添加新书这里添加即可. 当我点击删除的时候,只需要的就是除却删除的那一个书籍之后剩下的图书. ...

  5. 关于chrome控制台出现代码叠加页面不能正常显示大小问题

    见下图页面出现在chrome中的情况 描述状态:代码都变小了才出现控制台代码叠加问题 解决办法:使用鼠标滚轮放大代码就行啦,在设置里面让页面的大小显示为100%就可以了.

  6. 十一、java线程

    目录: 一.线程的基本概念 二.线程的创建和启动 三.线程的调度和优先级 四.线程的状态控制 五.线程同步 一.线程的基本概念 线程是一个程序内部的顺序控制流 线程和进程的区别: 每个进程都由独立的代 ...

  7. 树莓派 3b 串口启用

    网上搜到的方法都没用,不知道是不是系统版本的原因.以下方法是试出来的... uname -aLinux raspberrypi 4.14.79-v7+ #1159 SMP Sun Nov 4 17:5 ...

  8. sudALSA lib dlmisc.c:236:(snd1_dlobj_cache_get) Cannot open shared library /usr/lib/alsa-lib/libasound_module_pcm_pulse.so

    我使用的系统是kali,默认的浏览器为iceweasel.默认的浏览器很好用!! 但是,给浏览器安装flash后,播放视频,会报错:有视频,无声音. 下面给出我的解决方案:

  9. 类的内置方法__attr__介绍

    1.hasattr  getaddr  setaddr delattr 这四个函数同样也适用于类 class BlackMedium: feture="Ugly" def __in ...

  10. pageisELIgnored作用

    在page指令中有一个isELIgnored属性,其值为true则忽略EL表达式,为false则解析表达式