首页 > 系统相关 >《Mastering the FreeRTOS Real Time Kernel》读书笔记(1)堆内存管理

《Mastering the FreeRTOS Real Time Kernel》读书笔记(1)堆内存管理

时间:2023-10-11 11:38:08浏览次数:43  
标签:Real Kernel Heap FreeRTOS 读书笔记 内存 heap 空闲 字节

这是161204的版本,不完全覆盖目前最新版本的内核。

0.关于freeRTOS

首先提出了了在小型嵌入式系统中为何需要多任务管理的问题,介绍了freeRTOS的用途。然后开始做广告,吹了一波freeRTOS的好处。其中要注意一些关键的名词:任务优先级分配、任务通知、队列、信号量、互斥锁、软定时器、事件组、钩子函数等。这些内容会在后面的章节进行介绍。

1.FreeRTOS的文件结构

主要介绍在github上下载到的FreeRTOS包含哪些内容。

1.2 分布

可以将freeRTOS看成一个库,或者看成一个软件。其通过配置,可以运行在30多种不同的处理器架构上。而配置Freertos需要通过一个叫做FreeRTOSConfig.h的头文件。不同编译器或者处理器的该头文件不同,可以直接从众多例程中复制出来直接使用,或者微调后使用。
官方发行版中顶级目录有FreeRTOS(主要内核)和FreeRTOS-Plus(生态系统组件),其下分别都有Source和Demo两个文件夹。在FreeRTOS/Source中有task.clist.cqueue.ctimers.cevent—_groups.ccroutine.c这些源文件,有些总是需要,有些可选。
FreeRTOS/Source/portable中是一些针对特定编译器和架构的端口文件,相当于在不同国家旅游时的通行证。
头文件包含的路径一共要准备3个:FreeRTOS/Source/include、FreeRTOS/Source/portable/[compiler]/[architecture]、和指向FreeRTOSConfig.h的路径。

1.3 演示Demo

主要是教读者如何使用已有的演示Demo

1.4 创建FreeRTOS项目

包括修改Demo和从头开始创建两种方法。主要就是复制源文件进工程和修改端口文件。

1.5 数据类型和编码风格指南

FreeRTOS针对每个端口都有唯一的protmacro.h头文件,包含了针对不同单片机的两个特定数据类型TickType_t & BaseType_t。
变量名:c对应char、s对应int16_t(short)、l对应int32_t(long)、x对应BaseType_t。p对应指针变量前缀,u是无符号变量前缀。
函数名:函数前缀同变量名前缀。
格式化:一个制表符总是等于4个空格。
宏macro:宏的主体为全大写字母,小写字母作前缀,表示宏的定义位置。如taskENTER_CRITICAL(),该宏在task.h。pdTRUE = pdPASS = 1; pdFALSE = pdFAIL = 0;

注意:由于FreeRTOS需要在不同编译器上通过编译,所以其源代码包含的类型转换很多。

2.堆内存管理

注意:V9.0.0开始可以完全静态分配FreeRTOS应用程序,不需要包含堆内存管理器。这边主要介绍动态分配。
为什么需要动态内存分配。FreeRTOS每次创建内核对象时都需要分配RAM。但是内核对象其被删除时,需要释放对应的RAM。原本C库的malloc和free不适合单片机,所以重新设计相应的申请和释放函数pvPortMalloc()vPortFree()
为此,FreeRTOS准备了5种内存管理示例:heap_1.c, heap_2.c, heap_3.c, heap_4.c and heap_5.c。它们都在 FreeRTOS/Source/portable/MemMang 目录下。

Heap_1

无法使用动态内存的版本,没有使用vPortFree()。当调用pvPortMalloc()时,heap_1会在FreeRTOS堆空间内进行申请更小的空间,将申请的空间划分为任务控制块(TCB)和一个该任务专用栈。

Heap_2

Heap_4的原始版本,为了向后兼容而保留,建议使用增强的完整版Heap_4。
heap_2允许释放不用内存使其空闲,可以再次申请。再次申请的逻辑为:使用大小满足,且最接近请求字节数的空闲内存块。但是其不能将相邻的空闲内存合并,该功能在Heap_4中可以实现。
书例:5b、25b、100b的三块空闲内存,申请20b内存,该块内存将分配与25b空闲内存处,其中多余5b仍为空闲内存,就是此时还有5b、5b、100b三块空闲内存。
Heap_2适用于重复创建和删除任务的应用程序,前提是分配给创建的任务和堆栈大小不变。

Heap_3

使用标准库的malloc()和free()函数,因此堆的大小不是像前两者,由configTOTAL_HEAP_SIZE设置,而是由链接器配置决定。
通过临时挂起FreeRTOS调度器,Heap_3使malloc()和free()线程安全。这些内容会在第7章资源管理中涉及。

Heap_4

与heap_1和heap_2一样,heap_4的工作原理是将数组细分为更小的块,数组是静态分配的,并由configTOTAL_HEAP_SIZE确定尺寸。
与heap_2在分配时就有不同,书例:堆包含三个空闲内存块,按照它们在数组中出现的顺序,分别为5字节、200字节和100字节,调用pvPortMalloc()来请求20字节的RAM,第一个适合请求的字节数的空闲块是200字节,因此pvPortMalloc在返回指针之前将200字节拆分为一个20字节的块和一个180字节的块,返回的指针指向20字节的块,新的180字节块仍可以被pvPortMalloc调用。并不是申请最接近请求字节数的空闲内存块。
但是heap_4在释放内存时,会自动将相邻的空闲内存合并。注意只是相邻的。合并后会成为一个更大的空闲内存块,可用于申请。
heap_2和4申请内存、heap_4合并内存的依据都是因为每块空闲内存都有一小段空间是记录空闲内存信息的,通过这些信息可以精准地进行操作。
heap_4代表的数组起始地址是可以设置的,具体方法详见本书。

Heap_5

heap_5用于分配和释放内存的算法和heap_4相同,不同的是heap_5不限于从单个静态声明的数组分配内存,heap_5可以从多个独立的内存空间分配内存,当运行 FreeRTOS 的系统提供的 RAM 没有在系统内存映射中显示为单个连续(没有空间)块时,Heap_5 很有用。
在撰写本文时,heap_5 是唯一提供的内存分配方案,必须在调用 pvPortMalloc() 之前显式初始化。 Heap_5 使用 vPortDefineHeapRegions() API 函数初始化。 使用 heap_5 时,必须在创建任何内核对象(任务、队列、信号量等)之前调用 vPortDefineHeapRegions()
vPortDefineHeapRegions用于指定每个单独的内存区域的起始地址和大小,这些区域构成heap_5使用的总内存。

void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions );

每个单独的内存区域由HeapRegion_t类型的结构体描述,所有可用内存区域的描述作为 HeapRegion_t 结构数组传递到 vPortDefineHeapRegions()。

typedef struct HeapRegion
{
/* The start address of a block of memory that will be part of the heap.*/
uint8_t *pucStartAddress;
/* The size of the block of memory in bytes. */
size_t xSizeInBytes;
} HeapRegion_t;

比如定义三个不连续内存块可以使用如下代码。

/* Define the start address and size of the three RAM regions. */
#define RAM1_START_ADDRESS ( ( uint8_t * ) 0x00010000 )
#define RAM1_SIZE ( 65 * 1024 )
#define RAM2_START_ADDRESS ( ( uint8_t * ) 0x00020000 )
#define RAM2_SIZE ( 32 * 1024 )
#define RAM3_START_ADDRESS ( ( uint8_t * ) 0x00030000 )
#define RAM3_SIZE ( 32 * 1024 )
/* Create an array of HeapRegion_t definitions, with an index for each of the three RAM regions, and terminating the array with a NULL address. The HeapRegion_t structures must appear in start address order, with the structure that contains the lowest start address appearing first. */
const HeapRegion_t xHeapRegions[] =
{
{ RAM1_START_ADDRESS, RAM1_SIZE },
{ RAM2_START_ADDRESS, RAM2_SIZE },
{ RAM3_START_ADDRESS, RAM3_SIZE },
{ NULL, 0 } /* Marks the end of the array. */
};
int main( void )
{
/* Initialize heap_5. */
vPortDefineHeapRegions( xHeapRegions );
/* Add application code here. */
}

堆相关函数

xPortGetFreeHeapSize

返回调用该函数时未分配的堆空间总量

size_t xPortGetFreeHeapSize( void );

xPortGetMinimumEverFreeHeapSize

返回 FreeRTOS 应用程序自启动以来系统的历史最小可用堆空间量。
这两个函数都没有提供有关如何将未分配的内存分成更小的块的信息。

vPortGetHeapStats()

提供关于堆状态的附加信息。

Malloc调用失败的Hook函数

如果 pvPortMalloc() 因为请求大小的块不存在而无法返回 RAM 块,那么它将返回 NULL,则不会创建内核对象。此时执行,以处理这种情况。

void vApplicationMallocFailedHook( void );

标签:Real,Kernel,Heap,FreeRTOS,读书笔记,内存,heap,空闲,字节
From: https://www.cnblogs.com/HYBZ/p/17754986.html

相关文章

  • 《流畅的Python》 读书笔记 第二章数据结构(2) 231011
    2.5对序列使用+和*通常+号两侧的序列由相同类型的数据所构成,在拼接的过程中,两个被操作的序列都不会被修改,Python会新建一个包含同样类型数据的序列来作为拼接的结果+和*都遵循这个规律,不修改原有的操作对象,而是构建一个全新的序列l1=[1,2,3]l2=[4,5,6]print(id(l......
  • 《架构师之路:软件架构之美》第四,五章读书笔记
    第四章:系统可伸缩性的重要性第四章讨论了系统可伸缩性的重要性。在现代软件开发中,可伸缩性是一个关键概念,它涉及到系统在不同负载下的性能表现。以下是一些关键观点:可伸缩性是应对用户增长和数据量增加的关键。一个好的架构应该能够轻松扩展以满足这些需求,而不需要完全重新设......
  • KdMapper扩展实现之REALiX(hwinfo64a.sys)
    1.背景  KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。 2.驱动信息 驱动名称hwinfo64a.sys 时间戳5472......
  • 《复盘:对过去的事情做思维演练》读书笔记
    复盘是对过去所作的事情进行回顾、反思和探究,找出原因,找到规律,从而指导我们解决问题,帮助我们提升。对于复盘来说,回顾、反思、探究、提升,一个都不能少。复盘的由来复盘,原本是围棋中的一个术语。当下完一盘棋之后,要重新再棋盘上走一遍,看看哪些子下的好,哪些子下得不好,哪些地方可以......
  • 读书笔记——《软件需求》其二
    通过读《软件需求》,我学习到了很多,下面我拿具体的例子来说明一下:"Well-statedrequirementsarethekeytobuildingsystemsthecustomerswant."明确定义的需求是构建符合客户期望的系统的关键。"Thegoalofrequirementsengineeringistoidentifysystembehaviorstha......
  • This kernel requires an x86-64 CPU, but only detected an i686CPU. Unable to boot
    原文链接:https://www.longkui.site/program/other/i686/4759/ 0.背景买了一台小电脑,STARTC-8080型号,想给他装个Linux系统。给他装Ubuntu18的时候,开始报错:Thiskernelrequiresanx86-64CPU,butonlydetectedani686CPU.Unabletoboot–pleaseuseakernelapp......
  • 九月读书笔记1
    《程序员修炼之道-从小工到专家》这本书对于软件工程学习者来说是一本非常重要的书籍。在阅读中,我们可以学到很多实用的建议和思考。在第一节中,作者强调了程序员需要诚实、坦率和对担负的事情负责的态度,对于出现的问题需要提供可行的解决方案。第二节中,作者引用了破窗理论来说明......
  • Centos安装网卡驱动make时报错Kernel header files not in any of the expected locat
      Centos安装I219-LM网卡驱动  https://www.cnblogs.com/marixh/p/16927623.html查询适合我的网卡命令:12[root@192src]#lspci|grepnet00:1f.6Ethernetcontroller:IntelCorporationEthernetConnection(11)I219-LM发现适合我的版本是Int......
  • kernel如何根据dtb文件生成device tree
    kernel如何根据dtb文件生成devicetreedevicetreedtb文件中的内容会被内核组成了devicetree,整个tree上由两个数据结构组成:structdevice_node和structproperty。structdevice_node{ constchar*name; phandlephandle; constchar*full_name; structfwnode_handle......
  • 《流畅的Python》 读书笔记 231007(第二章第一部分)
    第2章数据结构ABC语言是Python的爸爸~很多点子在现在看来都很有Python风格:序列的泛型操作、内置的元组和映射类型、用缩进来架构的源码、无需变量声明的强类型不管是哪种数据结构,字符串、列表、字节序列、数组、XML元素,抑或是数据库查询结果,它们都共用一套丰富的操作:迭......