1. module_init() / module_exit()
include/linux/init.h
module_init()函数修饰模块的入口函数。根据是否定义MODULE,module_init()这个宏有不同的展开。
没有定义MODULE时,模块与内核链接成一个文件,module_init()修饰的函数被内核
177 #define __define_initcall(level,fn,id) \ 178 static initcall_t __initcall_##fn##id __used \ 179 __attribute__((__section__(".initcall" level ".init"))) = fn
207 #define device_initcall(fn) __define_initcall("6",fn,6) 212 #define __initcall(fn) device_initcall(fn)
258 /** 259 * module_init() - driver initialization entry point 260 * @x: function to be run at kernel boot time or module insertion 261 * 262 * module_init() will either be called during do_initcalls() (if 263 * builtin) or at module insertion time (if a module). There can only 264 * be one per module. 265 */ 266 #define module_init(x) __initcall(x);
arch/arm/kernel/vmlinux.lds文件确定了内核链接之后的代码布局。其中__initcall_start到__initcall_end之间就是由__define_initcall()宏定义的一些变量(实际上是函数指针),这些变量的值就是各module_init()修饰的函数的地址。
start_kernel()
-> rest_init()
-> 创建kernel_init线程,执行kernel_init函数
kernel_init()
-> do_pre_smp_initcalls()
do_pre_smp_initcalls()函数中依次调用__initcall_start到__initcall_end之间的函数指针。
定义了MODULE宏,则module_init()宏定义如下。
295 #define module_init(initfn) \ 296 static inline initcall_t __inittest(void) \ 297 { return initfn; } \ 298 int init_module(void) __attribute__((alias(#initfn)));
即模块入口函数统一都有一个别为init_module的别名。
2. insmod
insmod先检查ko文件的ELF标志,然后直接调用系统调用init_module()来做所有的工作。
kernel/module.c中有init_module系统调用。