深入理解 Linux 内核之module_init

module_init 是 Linux 内核模块机制中的一个宏,用于指定模块的初始化函数。当内核加载该模块时,这个初始化函数将被调用。理解 module_init 的原理有助于深入理解 Linux 内核模块的加载和初始化机制。

module_init 的定义

在 Linux 内核中,module_init 宏的定义如下:

#define module_init(initfn) \
	static inline initcall_t __inittest(void) \
	{ return initfn; } \
	__initcall(__inittest)

其中,initfn 是模块的初始化函数,通常由开发者定义。这个宏主要做了两件事:

定义一个静态内联函数 __inittest:这个函数返回 initfn,即开发者定义的初始化函数。
调用 __initcall:将 __inittest 注册为一个初始化调用。
__initcall
__initcall 宏是用于将初始化函数注册到一个特殊的内核段(section),这个段中的函数将在内核或模块初始化时被调用。它的定义如下:

#define __initcall(fn) __define_initcall(fn, 6)
#define __define_initcall(fn, id) \
	static initcall_t __initcall_##fn##id __used \
	__attribute__((__section__(".initcall" #id ".init"))) = fn

__initcall 宏通过 __define_initcall 将函数指针 fn 放入一个特定的 .initcall 段中。fn 在这里就是 __inittest 函数。.initcall 段的命名是由 id 决定的,不同的初始化优先级会对应不同的 id

初始化函数的调用顺序

Linux 内核中有不同的初始化阶段,每个阶段有不同的优先级,这些优先级对应不同的段(如 .initcall1.init.initcall2.init 等)。module_init 使用的优先级为 6,因此初始化函数会被放置在 .initcall6.init 段。

当内核或模块加载时,内核会遍历这些 .initcall 段,并调用其中注册的所有函数,从而执行模块的初始化逻辑。

工作原理总结

定义初始化函数:开发者定义一个模块初始化函数 initfn
使用 module_init 注册初始化函数:module_init 宏将 initfn 注册到 .initcall6.init 段。
内核加载模块:当内核加载该模块时,内核会遍历 .initcall 段,并调用所有注册的初始化函数,包括模块的 initfn
执行初始化逻辑:initfn 执行模块的初始化逻辑,如资源申请、数据结构初始化等。
例子

#include <linux/module.h>
#include <linux/init.h>

static int __init my_driver_init(void)
{
    printk(KERN_INFO "My driver is initialized\n");
    return 0;
}

module_init(my_driver_init);

在这个例子中:

my_driver_init 是模块的初始化函数。
module_init(my_driver_init)my_driver_init 注册为模块加载时的初始化函数。
当模块加载时,内核会调用 my_driver_init,执行其中的初始化代码。

总结

module_init 宏通过将模块的初始化函数注册到内核的 .initcall 段,使得在模块加载时,内核能够自动调用这些初始化函数。这个机制使得模块的初始化过程得以统一管理,并确保模块加载时必要的初始化操作能够正确执行。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值