首页 > 解决方案 > 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 设施:

  1. 动态链接?_dl_aux_init
  2. 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

标签: embeddedglibcnewlib

解决方案


在 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 功能。


推荐阅读