内核EXPORT_SYMBOL分析

本文详细介绍了EXPORT_SYMBOL宏的作用及应用场景,包括如何通过该宏导出内核函数的符号,以及在多个内核模块间共享这些符号的具体步骤。此外,还提供了具体的代码示例来展示如何在实际开发中应用这一机制。

在查看内核驱动代码的时候会经常看到在一些函数后面总会跟EXPORT_SYMBOL()这样的宏定义,通过网上查阅,它的作用大致总结如下:

1、定义说明

     把内核函数的符号导出,也可以理解成将函数名作为符号导出;符号的意思就是函数的入口地址,或者说是把这些符号和对应的地址保存起来的,在内核运行的过程中,可以找到这些符号对应的地址的。

2、相关处理

     (1)、对编译所得的.ko进行strip -S,处理掉调试信息,这样可以大大缩小ko文件的大小;

     (2)、使用KBUILD_EXTRA_SYMBOLS

主要使用于下面这样的场合:

有两个我们自己的模块,其中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加载时也会出错。

  1. // Module A (mod_a.c)  
  2. #include<linux/init.h>  
  3. #include<linux/module.h>  
  4. #include<linux/kernel.h>  
  5.   
  6. static int func1(void)  
  7. {  
  8.        printk("In Func: %s...\n",__func__);  
  9.        return 0;  
  10. }  
  11.   
  12. // Export symbol func1  
  13. EXPORT_SYMBOL(func1);  
  14.   
  15. static int __init hello_init(void)  
  16. {  
  17.        printk("Module 1,Init!\n");  
  18.        return 0;  
  19. }  
  20.   
  21. static void __exit hello_exit(void)  
  22. {  
  23.        printk("Module 1,Exit!\n");  
  24. }  
  25.   
  26. module_init(hello_init);  
  27. module_exit(hello_exit);  
  1. // Module B (mod_b.c)  
  2. #include<linux/init.h>  
  3. #include<linux/kernel.h>  
  4. #include<linux/module.h>  
  5.   
  6. static int func2(void)  
  7. {  
  8.        extern int func1(void);  
  9.        func1();  
  10.        printk("In Func: %s...\n",__func__);  
  11.        return 0;  
  12. }  
  13.   
  14. static int __init hello_init(void)  
  15. {  
  16.        printk("Module 2,Init!\n");  
  17.        func2();  
  18.        return 0;  
  19. }  
  20.   
  21. static void __exit hello_exit(void)  
  22. {  
  23.        printk("Module 2,Exit!\n");  
  24. }  
  25.   
  26. module_init(hello_init);  
  27. module_exit(hello_exit);  

`EXPORT_SYMBOL`和`EXPORT_SYMBOL_GPL`均用于将给定的符号导出到模块外,使这些符号能被其他模块使用。 ### 功能 - `EXPORT_SYMBOL`:允许导出的符号被任何许可证的模块使用。 - `EXPORT_SYMBOL_GPL`:用于导出符号(函数或变量),但只允许GPL许可证的模块来使用这些符号,确保了只有同样是GPL许可证的模块才能使用到这些导出的符号 [^2]。 ### 使用方法 - **符号导出位置**:符号必须在模块文件的全局部分导出,不能在函数中导出,因为这两个宏将被扩展成一个特殊用途的声明,而该变量必须是全局的。这个变量存储于模块的一个特殊的可执行部分(一个“ELF段”),在装载时,内核通过这个段来寻找模块导出的变量 [^1]。 - **代码示例**: ```c #include <linux/module.h> #include <linux/kernel.h> // 一个简单的内核函数 int my_kernel_function(int arg) { printk("my_kernel_function was called with arg = %d\n", arg); return arg * 2; } // 使用EXPORT_SYMBOL导出符号 EXPORT_SYMBOL(my_kernel_function); // 使用EXPORT_SYMBOL_GPL导出符号 // EXPORT_SYMBOL_GPL(my_kernel_function); MODULE_LICENSE("GPL"); ``` 若使用`EXPORT_SYMBOL_GPL`,还需在模块中使用`MODULE_LICENSE("GPL")`或者`MODULE_LICENSE("Dual BSD/GPL")`,之后才能在模块中引用该符号 [^2][^4]。 ### 区别 - **许可证限制**:`EXPORT_SYMBOL`允许导出的符号被任何许可证的模块使用,而`EXPORT_SYMBOL_GPL`限定了能够调用这个导出符号的其他代码也必须遵守GPL许可证 [^2]。 - **宏定义**: ```c #define EXPORT_SYMBOL(sym) \ __EXPORT_SYMBOL(sym, "") #define EXPORT_SYMBOL_GPL(sym) \ __EXPORT_SYMBOL(sym, "_gpl") ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值