module_init(my_init_function);
module_exit(my_exit_function);
首先分析这两个宏:
#define __used __attribute__((__used__))
#define LTO_REFERENCE_INITCALL(x) \
; /* yes this is needed */ \
static __used __exit void *reference_##x(void) \
{ \
return &x; \
}
#define __define_initcall(fn, id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" #id ".init"))) = fn; \
LTO_REFERENCE_INITCALL(__initcall_##fn##id)
#define device_initcall(fn) __define_initcall(fn, 6)
#define __initcall(fn) device_initcall(fn)
#define module_init(x) __initcall(x);
# define __section(S) __attribute__ ((__section__(#S)))
#define __exit_call __used __section(.exitcall.exit)
#define __exitcall(fn) \
static exitcall_t __exitcall_##fn __exit_call = fn
#define module_exit(x) __exitcall(x);
LTO_REFERENCE_INITCALL用于解决一个 LTO gcc 的问题:当一个模块中的变量没有被引用时,它将被移到程序的末尾。这会导致内核不喜欢的初始化调用的重新排序。添加一个虚拟引用函数来避免这种情况。该函数会被链接器删除。
展开主要的部分可以得到:
static initcall_t __initcall_my_init_function6 __attribute__((__used__))
__attribute__((__section__(".initcall6.init"))) = my_init_function;
static exitcall_t __exitcall_my_exit_function __attribute__((__used__))
__attribute__((__section__(".exitcall.exit"))) = my_init_function;
static initcall_t __initcall_my_init_function6
: 定义了一个静态变量__initcall_my_init_function6
,其类型为initcall_t
。__used
: 这是一个编译器指令或属性,用来告诉编译器强制使用(或者不要优化掉)标记了__used
的变量或函数。__attribute__((__section__(".initcall6.init")))
: 这是一个 GCC/Clang 特有的语法,用来指定变量应该放置在哪个特定的段(section)。在这里,.initcall6.init
可能是一个自定义的段名,用来存放初始化函数。数字6
可能表示了函数的优先级或者顺序。= my_init_function;
: 这部分初始化了__initcall_my_init_function6
,将其初始化为my_init_function
函数的值。- __exitcall_my_exit_function的解释同上理解