zoukankan      html  css  js  c++  java
  • linux内核及驱动开发中有关__init,__exit和__initdata的用法

    #define __init          __attribute__ ((__section__ (".init.text")))
    #define __initdata      __attribute__ ((__section__ (".init.data")))
    作用是把代码或者数据放到指定的section里去


    不是GCC的编译选项,是内核自己定义的。



    要了解Linux Kernel代码的分段信息,需要了解一下gcc的__attribute__的编绎属性或定义的函数或数,__attribute__主要用于改变所声明据的特性,它有很多子项,用于改变作用对象的特性。比如对函数,noline将禁止进行内联扩展、noreturn表示没有返回值、pure表明函数除返回值外,不会通过其它(如全局变量、指针)对函数外部产生任何影响。但这里我们比较感兴趣的是对代码段起作用子项section。

    __attribute__的section子项的使用格式为:

    __attribute__((section("section_name")))

    其作或用是将作用的函数数据放入指定名为"section_name"输入段。

    这里还要注意一下两个概念:输入段和输出段

    输入段和输出段是相对于要生成最终的elf或binary时的Link过程说的,Link过程的输入大都是由源代码编绎生成的目标文件.o,那么这些.o文件中包含的段相对link过程来说就是输入段,而Link的输出一般是可执行文件elf或库等,这些输出文件中也包含有段,这些输出文件中的段就叫做输出段。输入段和输出段本来没有什么必然的联系,是互相独立,只是在Link过程中,Link程序会根据一定的规则(这些规则其实来源于Link Script),将不同的输入段重新组合到不同的输出段中,即使是段的名字,输入段和输出段可以完全不同。

    其用法举例如下:

    int  var __attribute__((section(".xdata"))) = 0;

    这样定义的变量var将被放入名为.xdata的输入段,(注意:__attribute__这种用法中的括号好像很严格,这里的几个括号好象一个也不能少。)

    static int __attribute__((section(".xinit"))) functionA(void)

    {

    .....
    }

    这个例子将使函数functionA被放入名叫.xinit的输入段。

    需要着重注意的是,__attribute__的section属性只指定对象的输入段,它并不能影响所指定对象最终会放在可执行文件的什么段。

    2. Linux Kernel源代码中与段有关的重要宏定义

    A. 关于__init、__initdata、__exit、__exitdata及类似的宏

    打开Linux Kernel源代码树中的文件:include/init.h,可以看到有下面的宏定议:

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

    #define __initdata    __attribute__ (( __section__ (".init.data")))

    #define __exitdata   __attribute__ (( __section__ (".exit.data")))

    #define __exit_call  __attribute_used__ __attribute__ (( __section__ (".exitcall.exit")))

    #define __init_refok  oninline __attribute__ ((__section__ (".text.init.refok")))

    #define __initdata_refok __attribute__ ((__section__ (".data.init.refok")))

    #define __exit_refok noinline __attribute__ ((__section__ (".exit.text.refok")))

    .........

    #ifdef MODULE

    #define __exit  __attribute__ (( __section__ (".exit.text"))) __cold

    #else

    #define __exit __attribute_used__ __attribute__ ((__section__ (".exit.text"))) __cold

    #endif

    对于经常写驱动模块或翻阅Kernel源代码的人,看到熟悉的宏了吧:__init, __initdata, __exit, __exitdata。

    __init 宏最常用的地方是驱动模块初始化函数的定义处,其目的是将驱动模块的初始化函数放入名叫.init.text的输入段。当内核启动完毕后,这个段中的内存会被释放掉供其他使用。

    __initdata宏用于数据定义,目的是将数据放入名叫.init.data的输入段。其它几个宏也类似。

    另外需要注意的是,在以上定意中,用__section__代替了section。还有其它一些类似的宏定义,这里不一一列出,其作用都是类似的。


    from:

    http://blog.csdn.net/gao5528/article/details/6337409

  • 相关阅读:
    Effective Java 第三版——72. 赞成使用标准异常
    Effective Java 第三版——71. 避免不必要地使用检查异常
    Effective Java 第三版——70. 对可恢复条件使用检查异常,对编程错误使用运行时异常
    Effective Java 第三版——69. 仅在发生异常的条件下使用异常
    Effective Java 第三版——68. 遵守普遍接受的命名约定
    Effective Java 第三版——67. 明智谨慎地进行优化
    Effective Java 第三版——66. 明智谨慎地使用本地方法
    Effective Java 第三版——65. 接口优于反射
    Effective Java 第三版——64. 通过对象的接口引用对象
    Effective Java 第三版——63. 注意字符串连接的性能
  • 原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124321.html
Copyright © 2011-2022 走看看