EXPORT_SYMBOL的用法

本文介绍如何在Linux内核模块之间通过EXPORT_SYMBOL实现函数共享,包括示例代码解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

This is the classic method of exporting a symbol: dynamically loaded modules will be able to use the symbol as normal.

我们可以使用EXPORT_SYMBOL把要在kernel module之间共享的函数或者声明标记为共享,模块间就可以这些函数和变量了。

1// file A in module A
2
3 void func()
4
5 {
6
7   ...
8
9 }
EXPORT_SYMBOL(func)
//file B in module B

#include
<linux/module.h>

extern void func();

...

  

func函数就可以在这里使用啦。

转载于:https://www.cnblogs.com/renweiblog/archive/2011/07/24/2115664.html

<think>嗯,用户现在问的是EXPORT_SYMBOL_GPL和EXPORT_SYMBOL的区别。我之前帮他分析过内核模块加载失败的问题,其中提到了符号导出,可能他现在遇到了相关的问题,需要更深入的理解这两个宏的区别。 首先,我需要回忆这两个宏的基本定义。EXPORT_SYMBOL用于导出内核符号,使得其他模块可以使用这些符号,而EXPORT_SYMBOL_GPL则限制只有GPL兼容的模块才能使用这些导出的符号。这可能涉及到内核的许可证机制,GPL许可证的要求比较严格,而EXPORT_SYMBOL_GPL是为了确保只有遵守GPL的代码才能使用某些功能。 用户可能是在编写内核模块时遇到了符号无法访问的问题,或者在使用某些函数时被拒绝,因此想了解这两个宏的区别,从而解决模块加载或符号引用的问题。需要详细说明两者的使用场景和限制。 要注意的是,用户可能想知道为什么有些符号只能用EXPORT_SYMBOL_GPL导出,以及这对他们的模块开发有什么影响。比如,如果他们编写的模块不是GPL许可证,是否就无法使用某些内核函数。这时候需要解释许可证对模块的影响,以及内核如何通过这两个宏来强制执行许可证策略。 另外,用户可能对内核模块的许可证检查机制感兴趣。需要说明当模块使用EXPORT_SYMBOL_GPL导出的符号时,内核会检查调用模块的许可证是否标记为GPL兼容,否则会拒绝加载。这可能涉及到MODULE_LICENSE宏的设置,以及不同许可证(如GPL、MIT、BSD等)之间的兼容性。 还要提到实际开发中的情况,比如如果用户想使用某个EXPORT_SYMBOL_GPL导出的函数,但他们的模块不是GPL许可证,这时候该怎么办。可能需要建议他们修改许可证声明,或者寻找替代的函数,避免依赖GPL-only的符号。 此外,可以举一些例子,比如在内核源码中哪些符号是用GPL导出的,哪些不是,帮助用户更直观地理解。例如,某些核心功能或驱动程序可能只允许GPL模块使用,以确保代码的开源合规性。 最后,需要总结两者的主要区别,强调许可证的重要性,以及在内核开发中遵守许可证规定的必要性。用户可能需要根据他们的项目需求选择合适的导出方式,并确保模块的许可证与使用的符号兼容。</think>### **`EXPORT_SYMBOL` 与 `EXPORT_SYMBOL_GPL` 的核心区别** 在 Linux 内核开发中,`EXPORT_SYMBOL` 和 `EXPORT_SYMBOL_GPL` 都用于将内核符号(函数、变量)导出到模块可见的符号表中,但它们的 **许可证限制** 和 **使用场景** 有本质差异。以下是详细对比: --- ### **1. 许可证限制** | **特性** | **`EXPORT_SYMBOL`** | **`EXPORT_SYMBOL_GPL`** | |-------------------------|---------------------------------------|----------------------------------------| | **允许调用的模块许可证** | 任何许可证(包括闭源模块) | 仅限 GPL 兼容许可证(如 `GPL`, `MIT`) | | **内核检查机制** | 不强制检查模块许可证 | 强制检查模块的 `MODULE_LICENSE` 声明 | | **典型用途** | 通用内核接口(如基础 API) | 依赖 GPL 协议的核心功能或敏感操作 | --- ### **2. 技术实现差异** - **符号可见性** 通过 `EXPORT_SYMBOL` 导出的符号会被写入内核的通用符号表(`__ksymtab` 段),而 `EXPORT_SYMBOL_GPL` 导出的符号写入 GPL-only 符号表(`__ksymtab_gpl` 段)。 **模块加载时**,内核会校验模块的许可证是否与符号的导出类型匹配。 - **代码示例** 假设内核源码中定义了一个函数 `my_kernel_func()`: ```c // 导出为普通符号(允许任意模块调用) EXPORT_SYMBOL(my_kernel_func); // 导出为 GPL-only 符号(仅限 GPL 模块调用) EXPORT_SYMBOL_GPL(my_kernel_func_gpl); ``` 若模块未声明 GPL 兼容许可证(例如使用 `MODULE_LICENSE("Proprietary")`),调用 `my_kernel_func_gpl()` 时会导致加载失败: ```bash insmod: ERROR: could not insert module my_module.ko: Unknown symbol in module ``` --- ### **3. 实际应用场景** #### **`EXPORT_SYMBOL` 的典型用例** - 硬件无关的基础 API(如内存分配 `kmalloc`、定时器 `mod_timer`)。 - 跨模块共享的通用工具函数(如链表操作 `list_add`)。 #### **`EXPORT_SYMBOL_GPL` 的典型用例** - 涉及内核核心机制的功能(如进程调度、中断处理)。 - 硬件驱动中依赖 GPL 协议的高级功能(如直接操作寄存器的接口)。 - 内核开发者希望限制闭源模块使用的敏感接口。 --- ### **4. 验证方法** #### **查看符号的导出类型** ```bash # 查看符号表(注意后缀 ".gpl") grep "my_kernel_func" /proc/kallsyms # 输出示例: # ffffffff819b2000 T my_kernel_func [普通符号] # ffffffff819b2100 T my_kernel_func_gpl [gpl] [GPL-only 符号] ``` #### **模块许可证声明示例** ```c // 允许使用 GPL-only 符号 MODULE_LICENSE("GPL"); // 允许使用 GPL-only 符号(兼容 MIT 声明) MODULE_LICENSE("Dual MIT/GPL"); // 无法使用 GPL-only 符号 MODULE_LICENSE("Proprietary"); ``` --- ### **5. 绕过限制的风险与后果** 若强制在非 GPL 模块中使用 `EXPORT_SYMBOL_GPL` 导出的符号(例如修改内核或伪造许可证),会导致: 1. **法律风险**:违反 GPL 协议,可能引发版权纠纷。 2. **兼容性问题**:内核升级后符号可能被移除或修改。 3. **社区排斥**:代码无法被上游内核接受。 --- ### **总结** | **选择依据** | `EXPORT_SYMBOL` | `EXPORT_SYMBOL_GPL` | |-----------------------------|-----------------|---------------------| | 是否需要闭源模块调用 | 是 | 否 | | 是否涉及内核核心功能 | 否 | 是 | | 是否遵循 GPL 协议 | 可选 | 必须 | **设计建议**:优先使用 `EXPORT_SYMBOL_GPL` 导出敏感功能,以促进开源协作并避免滥用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值