顾炎武的爱国故事:module_init和module_exit

来源:百度文库 编辑:中财网 时间:2024/03/29 19:13:53

module_init和module_exit

分类: Linux内核 2011-12-17 15:43 37人阅读 评论(0) 收藏 举报 本文参照:http://blog.163.com/xinbuqianjin@126/blog/static/167563447201010221231507/http://www.360doc.com/content/11/0917/11/7473909_148946026.shtmlAndroid的module_init和module_exit的定义在common/include/linux/Init.hmodule_init和module_exit在MODULE宏有没有定义的情况下展开的内容是不同的。如果MODULE这个宏没有定义,基本上表明该模块是要编译进内核的(obj-y)。一、在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)此时应该最终会被忽略掉,因为编译进入内核的模块是不需要进行清理工作的。二、在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是在模块被卸载的时候调用。