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. 自学Linux Shell11.6-退出shell

    点击返回 自学Linux命令行与Shell脚本之路 11.6-退出shell shell运行的每一个命令都是使用 退出状态码 告诉shell它已经运行完毕.退出状态码是一个0~255的整数值,在命令结 ...

  2. python操作oracle实战

    import cx_Oracle conn = cx_Oracle.connect('ua_test/ua_test@192.32.98.15/oracledb') cur1 = conn.curso ...

  3. 【转】JVM性能调优监控工具jps、jstack、jmap、jhat、jstat使用详解

    http://www.cnblogs.com/therunningfish/p/5524238.html JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsol ...

  4. [转载]C++的顺序点(sequence point)和副作用(side effect)

    有关i=(++i)+(i++)这种东西的深入解释,不仅仅是简单粗暴undefined behavior. ==== 一.副作用(side effect) 表达式有两种功能:每个表达式都产生一个值( v ...

  5. luogu1979 华容道 (dijkstra+bfs)

    我想动某个点的话,一定要先把空白点移动到这个点旁边,然后调换这个点和空白点,一直重复 那么,我们就可以记一些状态(x,y,s) (s={0,1},{0,-1},{1,0},{-1,0}),表示我要动的 ...

  6. android广播(内部类)使用

    1.广播定义在一个单独的文件中 源码: public class MessageReceiver extends BroadcastReceiver{ @Override public void on ...

  7. cookies 不同端口 是可以共享的

    cookies 不同端口,是跨域吗? 我部署了两套系统在同一个ip上!8080,和8090! 这样.cookies,算跨域吗? 两套系统都记录了都有一个 historyItem的key的cookies ...

  8. 数据类型、位运算、sizeof()函数

    数据精度,依次升高.(负数必须使用有符号类型) 不同精度的数据间运算,所得结果为高精度类型. 数据类型详细信息如下图: 整型数据的数制:十进制(32).八进制(032,以0开头).十六进制(0x32, ...

  9. 误删除 linux 系统文件了?这个方法教你解决

    转载于互联网并适当的修改 误删除linux系统文件了?不用急,本文将给你一个恢复linux文件的方法,让你轻松应对运维中的各风险问题.方法总比问题多~ 说在前面的话 针对日常维护操作,难免会出现文件误 ...

  10. kubernetes控制器之DaemonSet

    转载于https://blog.csdn.net/bbwangj/article/details/82867472 什么是 DaemonSet? DaemonSet 确保全部(或者一些)Node 上运 ...