0

我有以下问题 - 我已经完成了烘焙 pi 课程,没有任何问题,然后我决定将这个纯 asm 与一些 C 链接起来。我已经这样做了,就我决定使用函数 sprintf 而言,一切都很好将 int 转换为 char*。现在,当我尝试编译时,我很享受以下错误

ctesty.c:(.text+0x20): undefined reference to 'sprintf' make: *** [build/output.elf] Error 1

当然我已经包含了stdio.h,我也尝试将这个lib直接包含在makefile中,但没有成功。

4

1 回答 1

3

您想与 链接libc.so。尝试-lc在您的 makefile 中添加链接步骤。

更好地理解问题后更新

Baking Pi示例构建了一个kernel.img代替通常的 Linux 内核运行的程序。这意味着 C 标准库不可用。您需要提供自己的sprintf()实现,例如:

  • 改编这个 BSD 许可的 ee_printf.c
  • 消除uart_send_char()
  • 通过制作函数参数ee_printf()来适应sprintf()buf

为什么用户空间 libc 不能在任何内核中没有源代码修改的情况下工作

从概念上讲:

  • C 标准库包含处理动态内存分配(malloc, free)、文件系统(fopenfclose所有 stdio)、环境变量(getenv)、错误处理设施等的设施setjmp longjmp
  • 考虑一下:您将如何malloc在操作系统下运行的程序中实现?
    • 答:您需要一些接口来向操作系统请求额外的内存,例如brksbrkmmapLinux 下。
    • 在操作系统内核中brkmmap等将不是分配内存的正确接口。
    • 因此,尽管大多数非玩具内核提供了malloc类似的设施,但它们将无法使用malloc未经修改的用户空间实现。
  • 在 OS 内核中,类似 的函数fopengetenv没有那么有用。大多数内核编写者选择不包含它们。
  • 因此,大多数内核不包含完整的 C 标准库实现,而只包含内核编写者认为有用的函数。

在更机械的意义上:

  • Baking Pi Makefile使用命令生成内核 ELF 映像$(ARMGNU)-ld --no-undefined $(OBJECTS) -Map $(MAP) -o $(BUILD)output.elf -T $(LINKER)。这不build/output.elf与任何 libc 实现链接,因此链接器将无法找到名为sprintf.
  • 当您使用 构建程序时gcc T.c -o T,gcc 会隐式链接到 libc 中,除非-nostdlib传递了 like 选项。

但在概念上很重要的一点是:

  • C 标准库中对内核有用的部分需要不同的实现
  • libc 的许多其他部分在内核中不会那么有用

有针对裸机环境的 C 标准库实现。例如,参见newlib

于 2014-06-23T13:39:32.040 回答