• Linux内核导出符号宏定义EXPORT_SYMBOL源代码分析



    资源:

    <include/linux/moudule.h>

    …….

    #ifndef MODULE_SYMBOL_PREFIX

    #define MODULE_SYMBOL_PREFIX ""

    #endif

    …….

    struct kernel_symbol       //内核符号结构

    {

           unsignedlong value;  //该符号在内存地址中的地址

           constchar *name;     //该符号的名称

    };

    ……

    #define __EXPORT_SYMBOL(sym,sec)                                

           externtypeof(sym) sym;                                                       

           __CRC_SYMBOL(sym,sec)                                           

           staticconst char __kstrtab_##sym[]                                

           __attribute__((section(“__ksymtab_strings”),aligned(1)))  

           =MODULE_SYMBOL_PREFIX#sym;                     

           staticconst struct kernel_symbol __ksymtab_##sym        

           __used                                                                         

           __attribute__((section(“__ksymatab”sec),unused))                  

           ={(unsignedlong)&sym,_kstrab_#sym} 

     

    #define    EXPORT_SYMBOL(sym)                  

                  __EXPOTR_SYMBOL(sym,””)

     

    #define    EXPORT_SYMBOL_GPL(sym)          

                  __EXPOTR_SYMBOL(sym,”_gpl”)

     

    #define    EXPORT_SYMBOL(sym)                  

                  __EXPOTR_SYMBOL(sym,”_gpl_future”)

     

     

    1、预备知识:

    在分析前,先了解例如以下相关知识:

    (1)#运算符,##运算符

    通常在宏定义中使用#来创建字符串 #abc就表示字符串”abc”等。

    ##运算符称为预处理器的粘合剂,用来替换粘合两个不同的符号,

    如:#definexName (n)  x##n

    则xName(4)  则变为x4

    (2)gcc的__attribute__属性:

    __attribute__((section(“section_name”)))的作用是将指定的函数或变量放入到名为”section_name”的段中。

    __attribute__属性加入能够再函数或变量定义的时候直接加入在定义语句中。

    如:int myvar__attribute__((section("mydata"))) = 0;

    表示定义了整形变量myvar=0;而且将该变量存放到名为”mydata”的section中

    关于gcc_attribute具体解释能够參考:http://blog.sina.com.cn/s/blog_661314940100qujt.html

     

     

    2、代码分析:

    举例说明:若要导出内核符号(内核函数)myfc,

    如调用           EXPORT_SYMBOL(myfc)

    展开为           __EXPORT_SYMBOL(myfc,””)

    展开为           

    static const char __kstrtab_myfc[]                                                                                           __attribute__((section(“__ksymtab_strings”),aligned(1)))  

     =MODULE_SYMBOL_PREFIX  myfc;                                               

    static const struct kernel_symbol __ksymtab_myfc                               

     __used

    __attribute__((section(“__ksymatab”),unsed))                                       

    ={(unsigned long)&sym,_kstrab_myfc} 

     

    由前面可知__attribute__是gcc中的属性(__used也是gcc属性),用于向指定的函数或者变量加入相关的属性。为了不影响对变量定义的理解,先将__attribute__属性掩盖。则上面的定义变为:

    static const char __kstrtab_myfc[]       =” myfc”;

    static const struct kernel_symbol__ksymtab_myfc={(unsigned long)&myfc,_kstrab_myfc}。

    //定义了一个字符数组__kstrtab_myfc[]用于存放导出的符号名myfc

    //定义了一个内核符号结构__ksymtab_myfc用于存放引出符号myfc在内存中的地址和名称。

    加入了__attribute__属性后。则表示:

    将字符数组__kstrtab_myfc[]放置到一个名为“__ksymtab_strings”的section中。

    将内核符号结构__ksymtab_myfc放置到一个名为”__ksymatab”的section中。

    若是调用了EXPORT_SYMBOL_GPL(myfc)。则相应的内核符号结构被放置到名 为”__ksymatab_gpl”的section中。

     

    3、总结:在内核符号导出中。调用了EXPORT_SYMBOL(sym),则会完毕下面操作:

    (1)   定义一个字符数组存放内核导出符号的名称。并放置到“__ksymtab_strings”的section中。

    (2)   定义一个内核符号结构用于存放导出符号的内存地址和名称,并放置到”__ksymatab”中。

    即通过EXPORT_SYMBOL(sym)告诉了内核以外的世界关于这个符号的两点信息:内核符号的名称和其内存地址。

          

     

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    我的开发板学习经验总结
    (大数据工程师学习路径)第四步 SQL基础课程----修改和删除
    稀疏矩阵
    (大数据工程师学习路径)第四步 SQL基础课程----select详解
    (大数据工程师学习路径)第四步 SQL基础课程----约束
    (大数据工程师学习路径)第四步 SQL基础课程----创建数据库并插入数据
    (大数据工程师学习路径)第四步 SQL基础课程----SQL介绍及mysql的安装
    (大数据工程师学习路径)第三步 Git Community Book----高级技能
    (大数据工程师学习路径)第三步 Git Community Book----中级技能(下)
    (大数据工程师学习路径)第三步 Git Community Book----中级技能(上)
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4853843.html
Copyright © 2020-2023  润新知