module_init和module_exit

轉自: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系統啓動過程當中被調用。
關於 device_initcall(fn) 的詳細內容請閱讀Linux內核中的xx_initcall》。
若是 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 是在模塊被卸載的時候調用。
相關文章
相關標籤/搜索