module_init调用过程


内核中很多模块都是通过module_init加载的
在头文件 init.h(<linux/init.h>)中对module_init有如下定义
#define module_init(x)  __initcall(x)
#define __initcall(fn)    device_initcall(fn)
#define device_initcall(fn)  __define_initcall("6",fn,6)
#define __define_initcall(level, fn, id) \
           static initcall_t __initcall_##fn##id__used\
          __attribute__((__section__(".initcall"level".init"))) = fn
根据宏的定义,如果调用module_init(pgio_init),实际上等于
static initcall_t __initcall_gpio_init6__used __attribute__((__section__(".initcall6.init"))) = gpio
initcall_t 为一函数指针类型
typedef int (*initcall_t)(void)
这个函数指针变量比较特殊的地方在于,变量放在了一个名为".initcall6.init"节中。
那又是如何调用起来的呢?结合vmlinux.lds.h中的描述


.initcall.init : AT(ADDR(.initcall.init) - (0xc0000000 -0x00000000)) {
   __initcall_start = .;
   *(.initcallearly.init) __early_initcall_end = .; *(.initcall0.init) *(.initcall0s.init) *(.initcall1.init) *(.initcall1s.init) *(.initcall2.init) *(.initcall2s.init) *(.initcall3.init) *(.initcall3s.init) *(.initcall4.init) *(.initcall4s.init) *(.initcall5.init) *(.initcall5s.init) *(.initcallrootfs.init) *(.initcall6.init) *(.initcall6s.init) *(.initcall7.init) *(.initcall7s.init)
   __initcall_end = .;
   }
以及do_initcalls:
static void __init do_initcalls(void)
{
initcall_t *call;
for (call = __initcall_start; call < __initcall_end; call++)
do_one_initcall(*call);
/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_work();
}
不难理解module_init中的初始化函数何时被调用了。
系统启动过程中  start_kernel()->rest_init()->kernel_init()->do_basic_setup()->do_initcalls()
这里,__initcal_start 指向.initcall.init的节首,而__initcall_end指向.initcall.init的节尾

你可能感兴趣的:(module_init调用过程)