The __init and __exit declarations are special kernel macros designed to tell the kernel to flag these
functions for special handling in cases where they are compiled in statically rather than included as
parts of modules.
The __init declaration allows the kernel to reclaim the space used by initialization
functions, while the __exit declaration tells the kernel to just plain ignore the function altogether. If
you’re only going to write your device driver as a module, with no possibility that it will be included
statically, it is perfectly safe to leave these special declarations out.
1 __init:
/* These macros are used to mark some functions or
* initialized data (doesn't apply to uninitialized data)
* as `initialization' functions. The kernel can take this
* as hint that the function is used only during the initialization
* phase and free up used memory resources after
*
* Usage:
* For functions:
*
* You should add __init immediately before the function name, like:
*
* static void __init initme(int x, int y)
* {
* extern int z; z = x * y;
* }
*
* If the function has a prototype somewhere, you can also add
* __init between closing brace of the prototype and semicolon:
*
* extern int initialize_foobar_device(int, int, int) __init;
*
* For initialized data:
* You should insert __initdata between the variable name and equal
* sign followed by value, e.g.:
*
* static int init_variable __initdata = 0;
* static char linux_logo[] __initdata = { 0x32, 0x36, ... };
*
* Don't forget to initialize data not at file scope, i.e. within a function,
* as gcc otherwise puts the data into the bss section and not into the init
* section.
*
* Also note, that this data cannot be "const".
其主要作用是初始化.
2)module_init:
/**
* module_init() - driver initialization entry point
* @x: function to be run at kernel boot time or module insertion
*
* module_init() will add the driver initialization routine in
* the "__initcall.int" code segment if the driver is checked as
* "y" or static, or else it will wrap the driver initialization
* routine with init_module() which is used by insmod and
* modprobe when the driver is used as a module.
*/
/**
* 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.
*/
注意一下init和cleanup這兩個函數定義的變化。__init宏使內建模組中的init函數在執行完成後釋放掉,不過可裝載的模組不受影響。如果你關心init函數什麼時候調用,這一點是很有用的。
還有個__initdata,和__init的作用基本上一樣,不過它是針對變數而不是函數的。
__exit宏會使那些內建到核心的模組省略掉cleanup函數,不過和__init一樣,對loadable模組沒影響。再說一遍,如果你關心cleanup啟動並執行時機,這是重要的。Built-in的驅動不需要cleanup,反正它們也不能退出,不過loadable式的模組顯然是需要一個的。
這些宏都定義在linux/init.h中,它們會釋放核心的記憶體。你啟動核心的時候會看到一些諸如Freeing unused kernel memory:236k freed,之類的資訊,這多半就是它們乾的。
_init修飾,以及.init開頭的節,在模組插入完畢運行之後,這一部分
的記憶體空間會被釋放,因此dump的時候這些資訊是無法得到的。
核心模組至少要有兩個函數:一個叫做init_module()的“start”初始化函數供insmod的時候調用,一個叫clean_module()的“end”清除函數供rmmod的時候調用。實際上,2.3.13之後的核心這兩個函數不再必須使用這兩個名字了。你給它們起什麼名字都可以,2.3節我會將具體怎麼做。給這兩個函數自己起名字其實是個挺好的主意,不過還是有很多人使用init_module和clean_module函數。L
很經典的,init_module函數會向核心註冊一些什麼東西,或者用自己的代碼替換核心的一些什麼功能(通常它們做點什麼動作之後還是會調用原來的函數)。而clean_module函數則會把init_module乾的事情做個了結,以便安全的卸載模組。
最後,每個核心模組都要包含linux/module.h。僅僅為了KERL_ALERT(2.1.1節會講到它)還需要在這個例子中包括linux/kernel.h。