1.module_init和module_exit
1.1 函数调用方式
#ifndef MODULE
#define module_init(x) __initcall(x);
#define module_exit(x) __exitcall(x);
#else /* MODULE */
#define early_initcall(fn) module_init(fn)
#define core_initcall(fn) module_init(fn)
#define core_initcall_sync(fn) module_init(fn)
#define postcore_initcall(fn) module_init(fn)
#define postcore_initcall_sync(fn) module_init(fn)
#define arch_initcall(fn) module_init(fn)
#define subsys_initcall(fn) module_init(fn)
#define subsys_initcall_sync(fn) module_init(fn)
#define fs_initcall(fn) module_init(fn)
#define fs_initcall_sync(fn) module_init(fn)
#define rootfs_initcall(fn) module_init(fn)
#define device_initcall(fn) module_init(fn)
#define device_initcall_sync(fn) module_init(fn)
#define late_initcall(fn) module_init(fn)
#define late_initcall_sync(fn) module_init(fn)
#define console_initcall(fn) module_init(fn)
/* Each module must use one module_init(). */
#define module_init(initfn) \
static inline initcall_t __maybe_unused __inittest(void) \
{ return initfn; } \
int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));
/* This is only required if you want to be unloadable. */
#define module_exit(exitfn) \
static inline exitcall_t __maybe_unused __exittest(void) \
{ return exitfn; } \
void cleanup_module(void) __copy(exitfn) __attribute__((alias(#exitfn)));
#endif
如果MODULE宏没有被定义,说明驱动是编译进了内核,会在内核引导时运行module_init
如果MODULE被定义,说明是模块,会在模块加载时调用module_init
,模块卸载时调用module_exit
1.2 内核引导时加载
--------------未完待续--------------
1.3 模块加载
/* Each module must use one module_init(). */
#define module_init(initfn) \
static inline initcall_t __maybe_unused __inittest(void) \
{ return initfn; } \
int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));
/* This is only required if you want to be unloadable. */
#define module_exit(exitfn) \
static inline exitcall_t __maybe_unused __exittest(void) \
{ return exitfn; } \
void cleanup_module(void) __copy(exitfn) __attribute__((alias(#exitfn)));
-
【第3行】本质上是一个函数__inittest,这个函数的返回值是一个函数指针,这个函数指针叫initcall_t类型(用typedef定义为int (*)(void))。这个函数__inittest的作用仅仅只是为了检测initfn函数指针是否是initcall_t类型,如果不是,编译器会报警告。
其中initcall_t在 include/linux/init.h中有如下定义,其本质就是函数指针。
typedef