/* 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)));
initcall_t 定义如下:
#ifndef __ASSEMBLY__
/*
* Used for initialization calls..
*/
typedef int (*initcall_t)(void);
typedef void (*exitcall_t)(void);
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
typedef int initcall_entry_t;
static inline initcall_t initcall_from_entry(initcall_entry_t *entry)
{
return offset_to_ptr(entry);
}
#else
typedef initcall_t initcall_entry_t;
static inline initcall_t initcall_from_entry(initcall_entry_t *entry)
{
return *entry;
}
#endif
module_init首先返回一个initfn的函数指针
__maybe_unused
定义在compiler_attributes.h中,用到unused的函数属性
#define __maybe_unused attribute((unused))
unused
This attribute, attached to a function, means that the function is meant to be
possibly unused. GCC does not produce a warning for this function.
参考gcc:
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
以下是变量的属性
unused
This attribute, attached to a variable, means that the variable is meant to be possibly unused. GCC does not produce a warning for this variable.
参考gcc:
https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes
此处返回值initcall_t是为了通过__inittest检测initfn是否是initcall_t 类型,如不是,则编译器报错
static inline initcall_t __maybe_unused __inittest(void)
{ return initfn; } \
故module_init起效果的应该是
int init_module(void) __copy(initfn) attribute((alias(#initfn)));
copy属性暂时没搞清楚
参考gcc:
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-copy-function-attribute
alias属性是GCC的特有属性,将定义init_module为函数initfn的别名。所以module_init(test_init)的作用就是定义一个变量名init_module,其地址和test_init是一样的。
问:alias(#initfn)里面的#什么作用?
答:在编译时,#的作用是,把后面的变元转化为带引号的串.