注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

民主与科学

独立之人格,自由之思想

 
 
 

日志

 
 

module_init和module_exit  

2011-12-13 15:39:14|  分类: Linux内核 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
Androidmodule_initmodule_exit的定义在common/include/linux/Init.h
module_initmodule_exitMODULE宏有没有定义的情况下展开的内容是不同的。
如果MODULE这个宏没有定义,基本上表明该模块是要编译进内核的(obj-y)。
一、在MODULE没有定义时
MODULE没有定义这种情况下,module_initmodule_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_modulegpio_init位于相同的地址偏移处。简言之,这种情况下模块的初始化函数在模块被载入的时候被调用。
module_exitinit_module同理只是module_exit是在模块被卸载的时候调用。
  评论这张
 
阅读(943)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017