Zephyr libc简介和malloc分析【转】
转自:https://lgl88911.gitee.io/2019/10/29/Zephyr-libc%E7%AE%80%E4%BB%8B%E5%92%8Cmalloc%E5%88%86%E6%9E%90/
本文简要介绍Zephyr的标准C库,并基于nrf52832分析malloc的heap来源。
本文只对开启了用户模式(CONFIG_USERSPACE)的情况进行分析,未开启的情况也大致相似,只是heap所在section会有所变化
标准C库
zephyr支援下面2种标准C库:
- minimal: 由zephyr实现的libc库
- newlib: 由编译工具链提供的libc库
minimal libc
minimal libc库是zephyr提供源代码,部分实现了常用的标准C函数,代码路径为zephyr/lib/libc/minimal,可以从下图大致看到minimal libc支援那些标准C API:
与minimal libc配置有关的是下面两项
- CONFIG_MINIMAL_LIBC_LL_PRINTF: printf支援%L,也就是long long的格式化打印
- CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE:malloc 使用heap的大小,如果不配置,无法使用malloc函数
zephyr默认情况下使用minimal libc, minimal libc在cortex-m4下只占用6K的size
newlib
Newlib是一个面向嵌入式系统的C运行库, 在arm提供的交叉编译工具集下面就包含了newlib的发行库,zephyr的lib/libc/newlib/libc-hooks.c中实现了newlib的桩函数,完成了对newlib的移植。
zephyr链接的时候会链接newlib的libm,libc,libgcc,因此这里面的函数在zephyr都可以用。
当配置了CONFIG_NEWLIB_LIBC=y后zephyr就使用newlib的标准C函数,和newlib配置相关的有下面几项
- CONFIG_NEWLIB_LIBC_FLOAT_PRINTF 在链接时加-u_printf_float, 支持printf浮点输出
- CONFIG_NEWLIB_LIBC_FLOAT_SCANF 在链接时加-u_scanf_float, 支持scanf浮点输入
- CONFIG_NEWLIB_LIBC_NANO 使用-specs=nano.specs进行编译链接,让导入的newlib更小
- CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE 指定malloc使用heap的大小,同时会改变heap的位置,后文详述
malloc heap
这里并不说明malloc实现的具体算法,只是对比看一下minimal和newlib在heap alloc上的差异
minimal malloc
实现
minimal 的malloc实现的代码在zephyr/lib/libc/minimal/source/stdlib/malloc.c下,可以从代码看出malloc是直接依赖于sys_mem_pool_alloc对heap的管理
void *malloc(size_t size)
|
heap
heap的定义如下
K_APPMEM_PARTITION_DEFINE(z_malloc_partition);
|
由K_APP_DMEM_SECTION产生的section会被放到app_smem section中,过程简要如下:
#define K_APP_DMEM_SECTION(id) data_smem_##id##_data --> z_malloc_mem_pool 在section data_smem_*中
|
脚本/home/frank/work/project/westz/zephyr/scripts/gen_app_partitions.py将上面信息解析后生成连接脚本build/zephyr/include/generated/app_smem_aligned.ld可以看到app_smem中包含了z_malloc_partition
SECTION_PROLOGUE(_APP_SMEM_SECTION_NAME,,)
|
因此可知minimal malloc使用的heap被放在app_smem section中。在nrf52832的SRAM map中,app_smem section是被放在内存的最开始处
newlib malloc
实现
newlib malloc是newlib内自己实现了内存管理算法,只是使用桩函数_sbrk来管理堆,代码在zephyr/lib/libc/newlib/libc-hooks.c中
void *_sbrk(int count)
|
heap
zephyr为newlib提供的heap会由于CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE的配置而不同,当配置了CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE, heap将会被放到app_smem section, 代码如下,分析过程可以参考前文的minimal
#if CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE
|
当不配置CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE时代码如下
#define USED_RAM_END_ADDR POINTER_TO_UINT(&_end)
|
可以看到heap是从_end开始,占用剩余所有的内存
参考
https://www.cs.ccu.edu.tw/~pahsiung/courses/esd/resources/newlib.pdf
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
2015-08-11 理解 Linux 配置文件【转】