内核模块 动态加载

内核模块动态加载分析:

module_init 宏定义

#define module_init(initfn) \
... ...
int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));
    给 module_init 修饰的入口起别名,为 init_module。
    __copy:属性的封装,拷贝模块入口API(initfn)的各种属性参数。

xx.mod.c文件解析

这个文件是模块生成的中间文件。内核构建过程的MODPOST阶段生成 Modename.mod.c 文件。

__visible struct module __this_module       与内核中加载的模块结构对应。拷贝加载模块时初始化。
__section(.gnu.linkonce.this_module) = {   在内核 setup_load_info 中,初始化内核的struct module变量
    .name = KBUILD_MODNAME,
    .init = init_module,                    内核中调用该 API 初始化模块。就是 module_init 修饰的别名。
#ifdef CONFIG_MODULE_UNLOAD
    .exit = cleanup_module,
#endif
    .arch = MODULE_ARCH_INIT,
};

内核层

info 指向用于装载模块的信息的 struct load_info,info->mod 中放置了一个临时指针。
layout_and_allocate 返回指向 __this_module 变量的指针;
即指向 .gnu.linkonce.this_module。该指针已被 move_module 复制到内核内存中的最后位置。
apply_relocations 执行动态链接之后,mod->init 和 mod->exit 将有它们的最终值。

  __this_module.init 始终是指向 init_module 的指针或默认为null;
    __this_module.exit 总是指向 cleanup_module 的指针或默认为null。
Linux内核模块编译、加载、运行机制分析、版本控制、许可声明、内核污染、模块传参、模块签名机制、out-of-tree动态模块编译及Makefile模板编写,尽在《Linux内核编程》,详情点击:王利涛老师个人淘宝店:Linux内核编程