轉自:http://blog.csdn.net/hudashi/article/details/7080071html
Android
的
module_init
和
module_exit
的定義在
common/include/linux/Init.h
module_init
和
module_exit
在
MODULE
宏有沒有定義的狀況下展開的內容是不一樣的。
若是
MODULE
這個宏沒有定義,基本上代表該模塊是要編譯進內核的(obj-y)。
1、在MODULE沒有定義時
在
MODULE
沒有定義這種狀況下,
module_init
和
module_exit
定義以下:
/**
* module_init() - driver initialization entry point
* @x: function to be run at kernel boot time or module insertion
*
* module_init() will either be called during do_initcalls() (if
* builtin) or at module insertion time (if a module). There can only
* be one per module.
*/
#define
module_init(x)
__initcall(x);
/**
* module_exit() - driver exit entry point
* @x: function to be run when driver is removed
*
* module_exit() will wrap the driver clean-up code
* with cleanup_module() when used with rmmod when
* the driver is a module. If the driver is statically
* compiled into the kernel, module_exit() has no effect.
* There can only be one per module.
*/
#define
module_exit(x)
__exitcall(x);
...........................................................
#define
__initcall(fn)
device_initcall(fn)
#define
__exitcall(fn)
\
static exitcall_t __exitcall_##fn __exit_call = fn
這裏
module_init(x)
被直接定義成了
__initcall(x)
。而
__initcall(x)
中又被定義成了
device_initcall(fn)
。
device_initcall(fn)的
fb函數將在Linux系統啓動過程當中(
start_kernel()
->
rest_init()
->
kernel_init()
->
do_basic_setup()
->
do_initcalls()
中)被調用,所以
module_init(x)也是在Linux系統啓動過程當中被調用。
若是
MODULE
這個宏沒有定義,基本上代表該模塊是要編譯進內核的(obj-y)。因此我以爲
module_exit(x)
此時應該最終會被忽略掉,由於編譯進入內核的模塊是不須要進行清理工做的。
2、在MODULE被定義時
.在MODULE被定義的狀況下(大部分可動態加載的driver模塊都屬於此, obj-m),module_init和module_exit定義以下:
/* Each module must use one module_init(). */
#define
module_init
(initfn) \
static inline initcall_t __inittest(void) \
{ return initfn; } \
int init_module(void) __attribute__((
alias
(#initfn)));
/* This is only required if you want to be unloadable. */
#define
module_exit
(exitfn) \
static inline exitcall_t __exittest(void) \
{ return exitfn; } \
void cleanup_module(void) __attribute__((
alias
(#exitfn)));
這段宏定義關鍵點是後面一句,經過
alias
將initfn變名爲
init_module
。前面那個__inittest的定義實際上是種技巧,用來對initfn進行某種靜態的類型檢查,若是閣下將模塊初始化函數定義成,好比,void gpio_init(void)或者是int gpio_init(int),那麼在編譯時都會有相似下面的warning:
GPIO/fsl-gpio.c: In function '__inittest':
GPIO/fsl-gpio.c:46: warning: return from incompatible pointer type
經過module_init將模塊初始化函數統一別名爲
init_module
,這樣之後在載入模塊的時候,在系統內部會調用sys_init_module()去找到init_module函數的入口地址。
若是
objdump -t gpio.ko
,就會發現
init_module
和
gpio_init
位於相同的地址偏移處。簡言之,這種狀況下模塊的初始化函數在模塊被載入的時候被調用。
module_exit
和
init_module
同理
,
只是
module_exit
是在模塊被卸載的時候調用。