embedded - glibc 可以在裸机或 RTOS 平台上运行吗?
问题描述
嵌入式专家,不做大的修改能做到吗?
我正在构建具有 Linux 内核和从睡眠状态恢复时运行的最小 RTOS 的固件。相同的工具链 aarch64-linux-gnu 用于 Linux 和 RTOS 代码。它不需要用于 RTOS 的单独裸机工具链的原因是因为供应商有自己的精简 C 运行时,他们使用它而不是 glibc。
但是那个糟糕的 C 运行时缺少很多功能,所以我们想使用一个功能更全的。我们可以使用 newlib ,但这需要第二个工具链,这是要避免的。
但我找不到任何使用 glibc 的裸机或 RTOS 项目。目前,它可以用 glibc 构建,但很快就崩溃了,几乎可以肯定是因为我们没有调用 glibc 初始化代码:
_start
__libc_start_main
__libc_csu_init (call C++ constructors for global variables)
main
https://github.molgen.mpg.de/git-mirror/glibc/blob/master/sysdeps/aarch64/start.S https://github.molgen.mpg.de/git-mirror/glibc/blob/master /csu/libc-start.c
但是看 __libc_start_main,它比 newlib 复杂得多。似乎它依赖于许多不存在的 Linux 设施:
- 动态链接?_dl_aux_init
- pthreads __pthread_initialize_minimal
从积极的方面来说,glibc 确实允许您覆盖弱定义的 sbrk 和 write,以便它们可以直接调用设备驱动程序代码,而不是对不存在的内核进行系统调用
更新:为我们工作意味着
1. malloc
2. printf,write to serial port, but not to actual files
3. C++ globals initialized correctly
4. no threading
解决方案
在 glibc 中,malloc
依赖于低级分配器,例如sbrk
(or mmap
)。您可能可以sbrk
在裸机目标上伪造一些东西,但是您必须排除所有间接malloc
依赖项(包括多线程支持)。
glibcprintf
实现与实现耦合fopen
,这依赖于dlopen
加载字符集转换代码(gconv
模块)。这甚至适用于静态链接的情况。如果没有一些影响深远的变化,真的没有办法逃脱动态链接器。
C++ 初始化应该相当容易正确,即使对于裸机目标也是如此。我认为您不需要任何 libc,只需一点点与您的目标需求相匹配的启动代码即可。(在某些目标上,在您的应用程序之前调用魔术函数就足够了_init
。)glibc 也为此提供了一些复杂的工具,但它们用于支持动态链接和dlopen
/ dlclose
。对于静态链接的二进制文件,它们不是必需的。
glibc 到非 Linux 的高质量移植。非 GNU 操作系统肯定是很多工作。如果目标是裸机或非 POSIX RTOS,您可能必须从 POSIX 垫片层开始。即使这样,结果也将是一个不完全 glibc 的目标,您仍然需要一个单独的工具链。
最好使用 newlib(或现有的 RTOS libc)并通过gnulib和类似项目获得缺少的 libc 功能。
推荐阅读
- python - 带有熊猫数据框的行之间的区别
- java - MapReduce 找不到符号
- sql - 将时间戳转换为本地时间 T-SQL
- google-cloud-firestore - Firestore 安全规则 - 使用自定义声明
- java - 运行时实例化全局可访问列表
- android - 如何修复此错误“找不到 android.room:room-compiler:2.2.4。”
- c - 显示大于 n = 5 的费马数时出现问题
- c# - 从 Azure 函数调用存储过程时,“System.Data.SqlClient.TdsParser”的类型初始化程序引发异常错误
- android - Android Studio - 为什么我的回收器视图卡住而不让我滚动到它的底部?
- kubernetes - 如何在 Kubernetes 中检查外部指标数据?