linux驱动模块 之 module_init()

 

注:以下讨论建立在内核 3.2.9基础之上。

linux驱动模块的加载由module_init() 宏功能出发,其用法例:

int __init fimc_md_init(void)

{

      int ret;

      request_module("s5p-csis");

      ret = fimc_register_driver();

      if (ret)

             return ret;

      return platform_driver_register(&fimc_md_driver);

}

 

module_init(fimc_md_init); 

从上面的例子可以看出,该宏函数的参数是__init 修饰的函数的函数名,故而可知其传入的是函数指针。那__init这个又是什么呢,我们把它展开来看一下,

#define __init __attribute__ ((__section__ (".text.init")))

好的,这里遇到了__attribute__ 为了更进一步的理解,这里不得不提及到 GNU C编译器扩展的一些知识作为辅助,其具体内容可见转载的《GNU C 扩展之__attribute__ 机制简介》这篇文章,这里只对__attribute__ 做简单的描述,__attribute__GNU C编译器的扩展功能,其作用是修改函数、变量和类型的编译属性,括号内的__section__表示段属性,整句的意思是将该宏修饰的函数或变量放入指定的段中,这里是.text.init 段,该例子中 __init 的作用就是 将函数fimc_md_init(void)编译的时候放入段.text.init 中,由于一些初始化操作只会运行一次,为了节约内存,在这些段内的代码运行完之后,linux会将其代码占用的内存释放掉。现在转过来继续聊module_init(),先把它逐层展开:

#define module_init(x)  __initcall(x);

#define __initcall(fn) device_initcall(fn)

#define device_initcall(fn)            __define_initcall("6",fn,6)

#define __define_initcall(level,fn,id) \

      static initcall_t __initcall_##fn##id __used \

      __attribute__((__section__(".initcall" level ".init"))) = fn

好的,基本展开完成,这里出现了initcall_t,查看一下定义,

typedef int (*initcall_t)(void);很清晰,就是typedef了个函数指针类型,连贯起来理解以上宏内容就是,定义了一个函数指针变量__initcall_##fn##id,然后将其初始化为fn,并通过__attribute__的编译选项,将其放入".initcall" level ".init" 中,这里的##是预编译时的字串连接符,该例子中把字串替换进去后的结果是

static initcall_t __initcall_fimc_md_init6 __used

      __attribute__((__section__(".initcall6.init"))) = fn

到现在我们明白了,module_init(x)的作用就是在.initcall6.init段中定义一个函数指针变量,然后将其初始化成 x。那这样做的具体作用是啥呢,这个时候我们有必要先看看.initcall6.init了。

上面说到的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值