glibc 在裸机或 RTOS 平台上工作吗?

Does glibc work on bare metal or RTOS platforms?

嵌入式高手,不做大的修改是否可行?

我正在构建同时具有 Linux 内核和从睡眠中恢复时运行的最小 RTOS 的固件。 Linux 和 RTOS 代码都使用相同的工具链 aarch64-linux-gnu。它不需要用于 RTOS 的单独裸机工具链的原因是因为供应商有自己的精简 C 运行时,他们使用它而不是 glibc。

但是那个做的很差的C runtime缺少了很多功能,所以我们想用一个功能更全的。我们可以使用 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. p线程__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(或 mmap)。您可能可以在裸机目标上伪造类似 sbrk 的东西,但您必须去除所有间接 malloc 依赖项(包括多线程支持)。

glibc printf 实现耦合到 fopen 实现,后者依赖 dlopen 加载字符集转换代码(gconv 模块)。这甚至适用于静态链接的情况。如果不进行一些影响深远的更改,确实无法逃脱动态链接器。

C++ 初始化应该相当容易正确,即使对于裸机目标也是如此。我不认为你需要任何 libc,只需要一点点符合你的目标需要的启动代码。 (在某些目标上,在您的应用程序之前调用魔术 _init 函数就足够了。)glibc 也有一些精心设计的工具,但它们用于支持动态链接和 dlopen/dlclose.对于静态链接的二进制文件,不需要它们。

glibc 的高质量移植到非 Linux。非 GNU 操作系统肯定需要大量工作。如果目标是裸机或非 POSIX RTOS,您可能必须从 POSIX 填充层开始。即便如此,结果也将是一个不太 glibc 的目标,您仍然需要一个单独的工具链。

最好使用 newlib(或现有的 RTOS libc)并通过 gnulib 和类似项目获得缺少的 libc 功能。