zoukankan      html  css  js  c++  java
  • 【转】编程之:EXPORT_SYMBOL使用

    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这些符号,这样才能找到对应的地址连接。

    使用方法:

       第一、在模块函数定义之后使用EXPORT_SYMBOL(函数名)
       第二、在掉用该函数的模块中使用extern对之声明
       第三、首先加载定义该函数的模块,再加载调用该函数的模块

    另外,在编译调用某导出函数的模块时,往往会有WARNING: "****" [**********] undefined!
    使用dmesg命令后会看到相同的信息。开始我以为只要有这个错误就不能加载模块,后来上网查了一下,发现这主要是因为在编译连接的时候还没有和内核打交道,当然找不到symbol了,但是由于你生成的是一个内核模块,所以LD不提示error,而是给出一个warning,寄希望于在insmod的时候,内核能够把这个symbol连接上。

    一个模块mod1中定义一个函数func1;在另外一个模块mod2中定义一个函数func2,func2调用func1。
    在模块mod1中,EXPORT_SYMBOL(func1);
    在模块mod2中,extern int func1();
    就可以在mod2中调用func1了

    EXPORT_SYMBOL示范

    比如有两个驱动模块:Module A和Module B,其中Module B使用了Module A中的export的函数,因此在Module B的Makefile文件中必须添加:

    KBUILD_EXTRA_SYMBOLS += /path/to/ModuleA/Module.symvers

    export KBUILD_EXTRA_SYMBOLS

    这样在编译Module B时,才不会出现Warning,提示说func1这个符号找不到,而导致编译得到的ko加载时也会出错。

    复制代码
    // Module A (mod_a.c)  
    #include<linux/init.h>  
    #include<linux/module.h>  
    #include<linux/kernel.h>  
      
    static int func1(void)  
    {  
           printk("In Func: %s...
    ",__func__);  
           return 0;  
    }  
      
    // Export symbol func1  
    EXPORT_SYMBOL(func1);  
      
    static int __init hello_init(void)  
    {  
           printk("Module 1,say hello world!
    ");  
           return 0;  
    }  
      
    static void __exit hello_exit(void)  
    {  
           printk("Module 1,Exit!
    ");  
    }  
      
    module_init(hello_init);  
    module_exit(hello_exit);  
    复制代码
    复制代码
    // Module B (mod_b.c)  
    #include<linux/init.h>  
    #include<linux/kernel.h>  
    #include<linux/module.h>  
    extern int functl(void);  
    static int func2(void)  
    {  
           func1();  
           printk("In Func: %s...
    ",__func__);  
           return 0;  
    }  
      
    static int __init hello_init(void)  
    {  
           printk("Module 2,is used Module 1 function!
    ");  
           func2();  
           return 0;  
    }  
      
    static void __exit hello_exit(void)  
    {  
           printk("Module 2,Exit!
    ");  
    }  
      
    module_init(hello_init);  
    module_exit(hello_exit);  
    复制代码
    在驱动加载的时候,一定要先加载定义function1的Module A模块,然后再加载调用function1的Module B的驱动模块。
    如下操作:
    insmod Module_A.ko  
    insmod Module_B.ko  


    转自:https://www.cnblogs.com/Caden-liu8888/p/7725293.html
  • 相关阅读:
    [LeetCode 1029] Two City Scheduling
    POJ 2342 Anniversary party (树形DP入门)
    Nowcoder 106 C.Professional Manager(统计并查集的个数)
    2018 GDCPC 省赛总结
    CF 977 F. Consecutive Subsequence
    Uva 12325 Zombie's Treasure Chest (贪心,分类讨论)
    Poj 2337 Catenyms(有向图DFS求欧拉通路)
    POJ 1236 Network of Schools (强连通分量缩点求度数)
    POJ 1144 Network (求割点)
    POJ 3310 Caterpillar(图的度的判定)
  • 原文地址:https://www.cnblogs.com/coreLeo/p/11759383.html
Copyright © 2011-2022 走看看