zoukankan      html  css  js  c++  java
  • EXPORT_SYMBOL的作用是什么

    http://www.cnblogs.com/riskyer/p/3221805.html

    EXPORT_SYMBOL只出现在2.6内核中,在2.4内核默认的非static 函数和变量都会自动

    导入到kernel 空间的, 都不用EXPORT_SYMBOL() 做标记的。

    2.6就必须用EXPORT_SYMBOL() 来导出来(因为2.6默认不到处所有的符号)。

    1、EXPORT_SYMBOL的作用是什么?

    EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代

    码就可以在您的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一个函数以符

    号的方式导出给其他模块使用。

    这里要和System.map做一下对比:


    System.map 中的是连接时的函数地址。连接完成以后,在2.6内核运行过程中,是不知道哪个符号在哪个地址的。
    EXPORT_SYMBOL 的符号, 是把这些符号和对应的地址保存起来,在内核运行的过程中,可以找到这些符号对应的地址。而模块在加载过程中,其本质就是能动态连接到内核,如果在模块中引 用了内核或其它模块的符号,就要EXPORT_SYMBOL这些符号,这样才能找到对应的地址连接。

    2、使用方法
    第一、在模块函数定义之后使用EXPORT_SYMBOL(函数名)
    第二、在掉用该函数的模块中使用extern对之声明

    第三、首先加载定义该函数的模块,再加载调用该函数的模块


    例如:

    一个模块mod1中定义一个函数func1;

    在另外一个模块mod2中定义一个函数func2,func2调用func1。

    在模块mod1中,EXPORT_SYMBOL(func1);

    在模块mod2中,extern int func1();

    就可以在mod2中调用func1了。


    (1)helloworld.c

    #include <linux/module.h>
    #include <linux/init.h>
    
    MODULE_LICENSE("GPL");
    
    static void hello_fun(void)
    {
      printk("##### helloworld####
    ");
    }
    EXPORT_SYMBOL(hello_fun);
    
    static int __init hello_init(void)
    {
       printk(KERN_ERR "#### hello world
    ");
       return 0;
    }
    
    static void __exit hello_exit(void)
    {
       printk(KERN_ERR "#### exit
    ");
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
    


    Makefile

    obj-m := hello.o
    hello-objs := helloworld.o
    
    KID := /lib/modules/`uname -r`/build
    PWD := $(shell pwd)
    
    all:
    	make -C $(KID) M=${PWD} modules
    
    clean:
    	rm -rf *.o .cmd *.ko *.mod.c .tmp_versions  
    



    (2)call-module.c

    #include <linux/module.h>
    #include <linux/init.h>
    
    extern void hello_fun(void);
    
    static int __init hello_init(void)
    {
       hello_fun();
       return 0;
    }
    
    static void __exit hello_exit(void)
    {
       printk(KERN_ERR "#### exit
    ");
    }
    
    MODULE_LICENSE("GPL");
    module_init(hello_init);
    module_exit(hello_exit);
    


    Makefile

    obj-m := call-module.o
    
    KID := /lib/modules/`uname -r`/build
    PWD := $(shell pwd)
    KBUILD_EXTRA_SYMBOLS=/usr/src/linux-headers-3.5.0-34-generic/Module.symvers
    
    KBUILD_EXTRA_SYMBOLS +=/home/snail/work/2.linux-driver/1.helloworld/Module.symvers
    
    all:
    	make -C $(KID) M=${PWD} modules
    
    clean:
    	rm -rf *.o .cmd *.ko *.mod.c .tmp_versions *.order *.symvers .*
    


    (3)

    加载 hello.ko

    sudo insmod ./hello.ko


    加载 call-module.ko 

    sudo insmod ./call-module.ko 


    观察 dmesg

    <4>[ 3837.857657] ##### helloworld####


    (4)注意事项

    加载call-module.ko可能会出现

    “NO SYMBOL VERSION FOR”问题


    解决:


    这是linux kernel 2.6.26 之后版本的bug (详细描述, 请看http://bugzilla.kernel.org/show_bug.cgi%3Fid%3D12446)
    并且这个bug不会被fix
    解决办法:

    (1)mod_a的Module.symvers放到mod_b的当前路径,从而编译mod_b,符号信息会自动连接进去.
    (2)或者在mod_b的makefile中使用KBUILD_EXTRA_SYMBOLS指定mod_a的Module.symvers,

     如:
    KBUILD_EXTRA_SYMBOLS=/mod_a/Module.symvers
    编译mod_b时,搜索Module.symvers的路径是:
    1, kernel source path, e.g. /usr/src/kernels/linux-2.6.28.10
    2, makefile中M=所指定的路径, 它等效于变量KBUILD_EXTMOD的值
    3, 变量KBUILD_EXTRA_SYMBOLS的值

    问题的本质:
    简单说来,就是小b生成的时候不知道小a symbol的校验码,小b加载的时候自然check 校验码出错。

  • 相关阅读:
    我的第一篇博客/markdown
    iOS开发编码建议与编程经验
    iOS 知识点梳理
    Objective-C中类和对象的介绍
    Linux虚拟机部署单机solr报错500解决方法之一
    day02:三元运算、布林非、列表等(20170214)
    day01:判断与循环(20170213)
    前端面试题大全2
    前端面试题大全
    [js] charAt()、charCodeAt()、fromCharCode()
  • 原文地址:https://www.cnblogs.com/jingzhishen/p/4362572.html
Copyright © 2011-2022 走看看