如何剪裁操作系统源码——移植FreeRTOS的内存管理模块到ARMV8裸片

如何剪裁操作系统源码

本文面向的需求场景是,为缺乏标准库实现的处理器IP移植内存管理模块,即为裸片部署C标准库中的 malloc()free() 函数。

具体做法是——从操作系统的内存管理组件中剪裁出必要的源码,适配到目标处理器的开发环境(SDK/IDE/CMAKE工程子目录)中。

1 定需求——理解内存管理/堆管理

1.1 C标准库中的内存管理方案

C标准库提供了一组内存管理函数,用于在C程序中进行动态内存分配和释放操作。这些函数主要包括malloc、calloc、realloc和free。

malloc函数: malloc函数用于分配指定大小的内存块,并返回指向该内存块的指针。其函数原型为:

void* malloc(size_t size);

它接受一个参数size,表示需要分配的内存空间的大小(以字节为单位)。malloc函数在堆内存中分配了一块连续的内存,并返回指向该内存块起始地址的指针。

calloc函数: calloc函数也用于分配指定数量和大小的内存块,并返回指向该内存块的指针。与malloc不同的是,calloc会将分配的内存块中的每个字节都初始化为0。其函数原型为:

void* calloc(size_t num, size_t size);

num参数表示需要分配的元素个数,而size参数表示每个元素的大小(以字节为单位)。calloc函数在堆内存中分配了大小为num * size的内存块,并返回指向该内存块起始地址的指针。

realloc函数: realloc函数用于调整先前分配的内存块的大小。其函数原型为:

void* realloc(void* ptr, size_t size);

ptr参数是指向先前通过malloc或calloc分配的内存块的指针,而size参数表示需要调整的大小(以字节为单位)。realloc函数根据新的大小重新分配内存块,并返回指向重新分配后内存块起始地址的指针。如果内存块不能被重新分配,realloc函数可能会创建新的内存块,并将原内存块的数据复制到新内存块中。

free函数: free函数用于释放先前通过malloc、calloc或realloc函数分配的内存块。其函数原型为:

void free(void* ptr);

ptr参数是指向先前分配的内存块的指针。通过调用free函数,该内存块将被标记为空闲,并可以被再次分配给其他内存需求。

1.2 需求剪裁

裸片程序受限于内存资源,一般是使用静态分配方法设计得到的,只在移植某些外设的驱动时需要提供基本的动态内存管理方法,很少有新增预分配的动态内存的需求。所以 realloccalloc 函数可以略去,这样咱的任务量就减少了一半啦。

2 找轮子——向操作系统学习

操作系统是对硬件的抽象,裸片上的绝大部分需求都可以在操作系统的源码中找到较为通用的实现,那么何必再造轮子呢,直接逮着操作系统的薅羊毛吧。

2.1 FreeRTOS中的内存管理方案

FreeRTOS 提供了几种堆管理方案,这些方案的复杂性和功能各不相同,分别适用于不同的需求场景,具体见下图。
在这里插入图片描述
总结性地说,FreeRTOS在源码目录 Source/Portable/MemMang 中为咱们提供了 5 种可选的内存管理模块的实现:

  • heap_1:极简版,不支持内存释放(没有 free 函数)
  • heap_2:支持释放,但不合并释放的内存块
  • heap_3:支持线程安全的 malloc 和 free 函数
  • heap_4:合并释放的内存块,避免内存碎片
  • heap_5:在 4 的基础上支持跨多个内存块进行分配

这儿咱们根据自己的需求选,本文选择 heap_2 移植,因为基本功能全面,且足够简单。

2.2 拉取源码

在源码树中找到 Source/Portable/MemMang/heap2.c,如下图。
在这里插入图片描述
打开就看到分配和释放函数触手可及,分别命名为 pvPortMallocvPortFree, 添加到咱的工程里,然后细看这个源文件的依赖,把依赖项从源码树里抠出来,舍弃不需要的文件,也就把内存管理模块从操作系统中剥离出来了。

2.3 剥离依赖项

heap_2.c包含了两个FreeRTOS相关的头文件—— FreeRTOS.h 和 task.h,后者是任务调度器相关的声明,咱们显然不需要,直接剔除。FreeRTOS是一些配置项的宏定义,咱们把与内存管理相关的剪切过来,不需要保留FreeRTOS.h整个文件。

在这里插入图片描述

然后是一个用于让管理的内存空间大小符合内存对齐需求的宏定义:

/* A few bytes might be lost to byte aligning the heap start address. */
#define configADJUSTED_HEAP_SIZE    ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )

configTOTAL_HEAP_SIZE 和 portBYTE_ALIGNMENT 都需要我们手动 #define
在这里插入图片描述
heap_2.c 还用到一个宏定义 portBYTE_ALIGNMENT_MASK
在这里插入图片描述
原先在FreeRTOS.h里,我们加到portmacro.h里:
在这里插入图片描述
剩下的就是一些基本的类型替换了,我们统一放到 portmacro.h 文件中:
在这里插入图片描述
projdefs.h 也是需要的,里面有 truefalse 的宏:
在这里插入图片描述

2.4 可用源码

Github仓库:memManPort

3 测试

可以用下面这个demo来测试移植结果的可用性,只要pb和pc值结果一致,那就基本正确了。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/55445.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

极狐GitLab 全新「价值流仪表盘」使用指南

本文来源:about.gitlab.com 作者:Haim Snir 译者:极狐(GitLab) 市场部内容团队 GitLab / 极狐GitLab 价值流仪表盘的使用相对简单,这种可以定制化的仪表盘能够让决策者识别数字化转型进程中的趋势及机遇。 如果你已经在用 GitLab…

爬虫008_流程控制语句_if_if else_elif_for---python工作笔记026

然后我们再来看一下这里的,判断,可以看到 再看一个判断,这里的布尔类型 第二行有4个空格,python的格式 注意这里,输入的age是字符串,需要转一下才行 int可以写到int(intput("阿斯顿法师打发地方")) 这样也可以

Pandas 的Merge函数详解

在日常工作中,我们可能会从多个数据集中获取数据,并且希望合并两个或多个不同的数据集。这时就可以使用Pandas包中的Merge函数。在本文中,我们将介绍用于合并数据的三个函数 merge、 merge_ordered、 merge_asofmerge merge函数是Pandas中…

【MySQL】对表中数据的操作

本期给大家带来的是MySQL下对表中数据的增删查改操作 目录 一、对表插入数据 1.1 单行数据插入 1.2 多行数据插入 1.3 插入冲突时更新数据 1.4 替换式插入 1.5 插入查询结果 二、对表中数据进行查询 2.1 基本select 2.1.1 使用select查询表中数据 2.1.2 使用select…

2023-08-05——JVM 栈

栈 stack 栈:数据结构 程序数据结构算法 栈:先进后出,后进先出 好比一个:桶 队列:先进先出(FIFO :First Input First Out) 好比一个:管道 栈:喝多了吐。队列…

Killing LeetCode [82] 删除排序链表中的重复元素 II

Description 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 Intro Ref Link:https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/ Difficulty:Medium T…

【Change】50 Matplotlib Visualizations, Python实现,源码可复现

详情请参考博客: Top 50 matplotlib Visualizations 因编译更新问题,本文将稍作更改,以便能够顺利运行。 1 Time Series Plot 时间串行图用于可视化给定指标如何随时间变化。在这里,您可以看到1949年至1969年间航空客运量的变化。查看此免费…

JDBC用法小结

JDBC用法小结 本文实例总结了JDBC的用法。分享给大家供大家参考。具体分析如下: DriverManger:驱动管理器类 要操作数据库,必须先与数据库创建连接,得到连接对象 public static Connection getConnection(String url, String username,Str…

【unity】Pico VR 开发笔记(视角移动)

【unity】Pico VR 开发笔记(视角移动) 视角移动是简单的基础功能,这里区别于头显定位获得的小范围位移,是长距离不影响安全边界的位移方式。的常见的位移方式有两种,其一是触发后瞬间传送到指定位置,其次是…

第5章 运算符、表达式和语句

本章介绍以下内容: 关键字:while、typedef 运算符:、-、*、/、%、、--、(类型名) C语言的各种运算符,包括用于普通数学运算的运算符 运算符优先级以及语句、表达式的含义 while循环 复合语句、自动类型转换和强制类型转换 如何编写…

JavaWeb项目工程结构介绍

介绍idea创建Web项目工程下的项目结构(新建的web工程) 了解目录大致作用 一级目录 :.idea、out、src、web、工程名.iml .idea目录:记录了IntelliJ IDEA 的配置目录,包含项目的配置信息、工程设置、构建配置等。它是用来存储项目…

Hive终端命令行打印很多日志时,如何设置日志级别

示例:use test; 切换到test数据库时,输出很多日志信息不方便看结果,如下图。 解决方法: 退出hive命令行界面(ctrlC)执行“vi /usr/local/apache-hive-3.1.2-bin/conf/log4j.properties”命令,创…