linux symbol文件,LINUX EXPORT_SYMBOL_GPL及EXPORT_SYMBOL导出函数

本文介绍了EXPORT_SYMBOL和EXPORT_SYMBOL_GPL宏的功能,这两种宏用于在Linux内核模块间导出函数,使得其他模块能够调用这些函数。文章还讨论了如何通过不同的命令查看内核和模块中的已导出符号。

EXPORT_SYMBOL(),这个宏也是将函数导出让所有模块都可以使用,而EXPORT_SYMBOL_GPL()这个宏主要是给有GPL认证的模块使用。

2)、EXPORT_SYMBOL标签内定义的函数对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用。

3)、EXPORT_SYMBOL(符号名);  EXPORT_SYMBOL_GPL(符号名)

一)主要作之一: 内核"导出"的符号表,这个表在insmod 时候会用到.

1./proc/kallsyms

cat /proc/kallsyms会打印出内核当前的符号表,例如:

...

d8834a24 t snd_free_sgbuf_pages [snd_page_alloc]

d8834ab5 t snd_malloc_sgbuf_pages [snd_page_alloc]

c014f906 U kmem_cache_alloc [snd_page_alloc]

c0106dcd U dma_alloc_coherent [snd_page_alloc]

...

其中第一列是该符号在内核地址空间中的地址;第二列是符号属性,小写表示

局部符号,大写表示全局符号,具体含义参考man nm; 第三列表示符号字符串.

这里只能显示EXPORT_SYMBOL,EXPROT_SYMBOL_GPL处理过的符号。

2.System.map内核符号文件

通过more /boot/System.map 可以查看内核符号列表。

可以显示编译好内核后所有在内核中的符号,模块中的要另行查看。

3.通过nm vmlinux也可以查看内核符号列表

可以显示编译好内核后所有在内核中的符号,模块中的要另行查看。

4.通过nm module_name可以查看模块的符号列表

但是得到是相对地址,只有加载后才会分配绝对地址。比如:e1000模块,如果e1000中的符号经过EXPORT_SYMBOL处理,

等加载后,我们可以通过more /boot/System.map和nm vmlinux命令查看到,但是没有EXPORT_SYMBOL的,不能查看。

代码如:

int __gpio_cansleep(unsigned gpio)

{

struct gpio_chip *chip;

<think>嗯,用户问的是为什么Linux内核中要用EXPORT_SYMBOL或者EXPORT_SYMBOL_GPL导出符号。首先,我得回忆一下这两个宏的作用。它们都是用来将内核中的函数或者变量导出,使得其他模块可以使用这些符号。不过用户可能已经知道这点,所以需要更深入的解释。 首先,用户可能想知道为什么需要显式地导出符号,而不是默认所有符号都可用。这时候需要解释内核模块的动态加载机制,模块是独立的,不能自动访问内核或其他模块的符号,除非显式导出。这样设计的好处是减少耦合,增强安全性,避免模块之间的意外依赖。 然后,用户可能对EXPORT_SYMBOLEXPORT_SYMBOL_GPL的区别感兴趣。需要解释GPL版本是要求使用该符号的模块也必须遵循GPL协议,这是LinuxGPL兼容性的强制措施。而普通的EXPORT_SYMBOL则没有这个限制,但可能用于非GPL的代码,这可能涉及到许可证的问题。 接下来,用户可能想知道实际应用中的例子。比如内核中的某些子系统导出函数供设备驱动使用,或者硬件厂商的驱动如何利用这些导出的符号。这时候需要举一些例子,比如文件系统操作、内存管理函数等,这些通常会被导出。 另外,用户可能想了解导出符号的机制,比如符号表在内核中的存储方式,模块加载时如何解析这些符号。这部分可能需要稍微深入一点,但保持简洁,避免过于技术化。 还需要提到使用这些宏的注意事项,比如不能随意导出符号,否则会导致内核接口的不稳定,或者安全风险。内核开发者需要谨慎决定哪些符号需要导出,保持最小权限原则。 用户可能还会有疑问,如果模块不导出符号,是否就无法被其他模块使用?这时候需要解释静态链接和动态加载的区别,以及模块之间的依赖关系如何处理。 最后,总结一下这两个宏的作用和重要性,强调它们在Linux内核模块化设计中的关键角色,以及维护内核健康生态的意义。</think>在Linux内核开发中,`EXPORT_SYMBOL` 和 `EXPORT_SYMBOL_GPL` 是用于将函数或变量(统称为“符号”)导出给其他内核模块使用的关键机制。以下是其设计目的和用法的分步解释: --- ### 1. **内核模块化的需求** Linux内核是模块化设计的,允许通过动态加载模块(`.ko`文件)扩展功能。但默认情况下: - **模块间隔离**:每个模块是独立的,无法直接访问其他模块或内核内部的符号(函数、变量)。 - **符号共享需求**:某些基础功能(如内存分配`kmalloc`、设备驱动接口)需要被多个模块复用。 **解决方式**:通过显式导出符号,声明哪些符号可以被外部模块访问。 --- ### 2. **`EXPORT_SYMBOL` 的作用** - **导出符号**:将符号添加到内核的全局符号表中,允许其他模块调用它。 - **示例**: ```c // 在内核源码中定义并导出一个函数 void my_function(void) { // ... } EXPORT_SYMBOL(my_function); // 导出符号 ``` - **使用场景**:允许任何模块(无论是否开源或遵循GPL)使用该符号。 --- ### 3. **`EXPORT_SYMBOL_GPL` 的作用** - **限制导出范围**:仅允许遵循**GPL许可证**的模块使用该符号。 - **法律约束**:强制调用者遵守GPL协议,避免闭源模块滥用内核功能。 - **示例**: ```c // 导出一个仅限GPL模块使用的函数 void my_gpl_function(void) { // ... } EXPORT_SYMBOL_GPL(my_gpl_function); // 仅GPL模块可用 ``` --- ### 4. **为何需要显式导出?** - **安全性**:避免内核内部接口被滥用。未导出的符号对其他模块不可见,减少攻击面。 - **稳定性**:内核开发者仅维护导出的接口,隐藏内部实现细节。 - **许可证合规**:通过`EXPORT_SYMBOL_GPL`保护GPL代码的“传染性”。 --- ### 5. **技术实现** - **符号表存储**:导出的符号会被记录在`/proc/kallsyms`(内核符号表)中。 - **模块加载过程**: 1. 模块加载时,通过符号表解析依赖的符号。 2. 若符号未导出,加载会失败(报错`Unknown symbol`)。 --- ### 6. **实际应用场景** - **设备驱动**:导出硬件操作接口供其他驱动复用。 - **核心子系统**:如文件系统、网络栈导出通用API。 - **开源与闭源冲突**:闭源驱动无法使用`EXPORT_SYMBOL_GPL`导出的符号。 --- ### 7. **总结** - **`EXPORT_SYMBOL`**:通用导出,无许可证限制。 - **`EXPORT_SYMBOL_GPL`**:仅限GPL兼容模块使用。 - **核心价值**:平衡模块化扩展、代码安全性和法律合规性。 --- 通过这种机制,Linux内核既实现了灵活的模块化扩展,又保护了核心代码的稳定性和开源生态的健康发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值