如何做编译器/连接解决内核API像从Linux上的模块称为“的printk”(how does co

2019-06-25 08:29发布

我写了一个样本hello.ko内核模块:

#include <linux/module.h>      /* Needed by all modules */
#include <linux/kernel.h>      /* Needed for KERN_INFO */

int init_module(void)
{
        printk(KERN_INFO "Hello world.\n");
        return 0;
}

void cleanup_module(void)
{
        printk(KERN_INFO "Goodbye world 1.\n");
}

在这里,我曾用“printk的”方法,它是一个内核API被Linux露出。 我可以看到在Linux中“的/ proc / kallsyms”导出的符号。 我很好奇,想知道怎么做的gcc / LD链接称为内核API? 请问GCC / LD从“的/ proc / kallsyms”或其他文件,并执行链接获取内核方法的地址? 如果是的话,怎么办GCC / LD了解吗? 我不能告诉任何选项。

Answer 1:

Linux内核的模块加载器基本上包含一个专用的运行时链接。 该.ko文件是真的喜欢其他任何一个目标文件,因此它带有一个符号表。 如果运行nm它( nm <path/to/some_module.ko>你会看到很多的符号标为“U”,即,“未定义”。 这包括由模块用于核心内核函数的符号,诸如printk__kmallockfree等,但在许多情况下也可由其他模块来实现的符号。

当模块被加载,内核通过模块未定义的符号运行,查找起来的(运行时)符号表,修补相关的存储位置,就像任何其他连接器。 如果有任何未定义符号是不是已经在符号表中,装载会失败(易于使用演示insmod ,而不是modprobe ,因为它不会加载依赖)。 它还添加模块导出符号表的其他模块使用任何符号,跟踪依赖关系,所以你不能把抽出了另一个使用的模块。 伊利亚Matveychikov已经挂在评论模块加载相关的代码,如果你想知道所有的血淋淋的细节,这将有助于。



文章来源: how does compiler/linker resolves kernel API like 'printk' called from a module on linux