【问题标题】:Why can't we use C standard library functions in kernel development?为什么我们不能在内核开发中使用 C 标准库函数?
【发布时间】:2012-11-21 02:01:40
【问题描述】:

我刚开始学习内核开发并且有一点疑问。为什么我们不能在内核开发中使用 c 函数与 c 库链接后使用它?为什么内核从不与 c 库链接,而是拥有自己的一些标准 c 函数的实现,例如 printk() 而不是 printf()。如果内核是用 c 编写并在 c 编译器的帮助下编译的,那么为什么我们不能使用 c 库中的标准函数呢?

【问题讨论】:

    标签: linux linux-kernel


    【解决方案1】:

    因为您熟悉的 GNU C 库是针对用户模式而不是内核模式实现的。内核无法访问用户空间 API(这可能会调用 Linux 内核的系统调用)。

    来自KernelNewbies FAQ

    我可以在内核中使用库函数吗?

    通常可供用户空间程序员使用的系统库(例如 glibc、libreadline、libproplist 等)对内核程序员来说是不可用的。当一个进程被加载时,加载器会自动将所有依赖库加载到进程的地址空间中。内核程序员无法使用这种机制:忘记 ISO C 库吧,唯一可用的是内核中已经实现(和导出)的内容以及您可以自己实现的内容。

    请注意,可以“转换”库以在内核中工作;但是,它们不太适合,过程繁琐且容易出错,并且堆栈处理可能存在重大问题(内核仅限于少量堆栈空间,而用户空间程序没有此限制)导致随机内存损坏。

    许多常用的功能已经在内核中实现了,有时在“轻量级”版本中,它们的功能不如用户空间对应物。在从头开始编写自己的版本之前,请务必对您可能使用的任何函数的标题进行 grep。一些最常用的在 include/linux/string.h 中。

    当您觉得需要一个库函数时,您应该考虑您的设计,并问问自己是否可以将部分或全部代码移至用户空间。

    如果您需要使用标准库中的函数,您必须重新实现该功能,原因很简单 - 没有标准 C 库。

    C 库基本上是在 Linux 内核(或其他操作系统的内核)之上实现的。

    例如,C 库的 mkdir(3) 函数基本上只不过是 Linux 内核的系统调用 mkdir(2) 的包装器。

    http://linux.die.net/man/3/mkdir http://linux.die.net/man/2/mkdir

    【讨论】:

    • 但是让我们说(为了理解起见)我写了一些 c 代码并在将它与标准 c 库链接后编译它。这反过来会产生一些可以由机器执行的二进制文件。如果我将此二进制文件放入内核会发生什么?为什么它不执行,因为处理器的指令集不取决于程序是在用户空间还是内核空间中运行。当然,这段代码可能会调用系统调用。但是如果我们在执行我写的代码之前加载内核的那部分呢?
    • 这不仅仅与机器码有关,还与二进制格式有关。您正在尝试将 Linux 二进制文件与非 Linux 二进制文件链接。
    • 您能否详细说明一下。我真的不明白
    • " 我写了一些 c 代码并在链接后编译它" -- 代码被编译,然后与静态库链接,或者在加载时与动态库链接执行。 "产生一些可以被机器执行的二进制文件" -- 这个二进制文件很少是原始图像文件。更常见的是操作系统的加载程序知道如何处理(即与库链接)然后让其执行的可执行文件类型(例如 COFF 或 EABI)。您似乎低估了现代操作系统中“执行程序”的复杂性。
    • "与标准 c 库链接,如 stdio.h 等" -- 头文件未链接,它们是可以包含的源代码 在编译步骤中。这至少是“链接”的第二次误用,这让我想知道您是否对您正在使用的这些术语有正确的理解。 “为什么不直接使用 c 库” Oleksandr 已经回答了这个问题;重读答案的第一行。顺便说一句,内核对stdio.h 中声明的函数没有用处。内核实现了那些 I/O 函数,而不是使用它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 2023-02-02
    相关资源
    最近更新 更多