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。