`
shaojiashuai123456
  • 浏览: 262737 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
社区版块
存档分类
最新评论

EXPORT_SYMBOL 与 EXPORT_SYMBOL_GPL 转载

阅读更多
1.EXPORT_SYMBOL

EXPORT_SYMBOL( my_pub_func);
在预编译阶段会解析为:
extern void *__crc_my_pub_func __attribute__((weak));
static const unsigned long __kcrctab_my_pub_func __attribute__((__used__)) __attribute__((section("__kcrctab" ""), unused)) = (unsigned long) &__crc_my_pub_func;
static const char __kstrtab_my_pub_func[] __attribute__((section("__ksymtab_strings"))) = "" "my_pub_func";
static const struct kernel_symbol __ksymtab_my_pub_func __attribute__((__used__)) __attribute__((section("__ksymtab" ""), unused)) = { (unsigned long)&my_pub_func, __kstrtab_my_pub_func };
很显然__ksymtab_my_pub_func存储了my_pub_func的地址和符号信息,该符号对应的地址
只有insmod后才会确定;
__ksymtab_my_pub_func会链接到__ksymtab section,__ksymtab section中的所有内容就构成了
内核"导出"的符号表,这个表在insmod 时候会用到.
2./proc/kallsyms
cat /proc/kallsyms会打印出内核当前的符号表,例如:
...
d8834a24 t snd_free_sgbuf_pages [snd_page_alloc]
c0180d7a U create_proc_entry [snd_page_alloc]
d88341d8 T snd_dma_free_pages [snd_page_alloc]
c013d858 U __get_free_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处理过的符号。
3.System.map内核符号文件
通过more /boot/System.map 可以查看内核符号列表。
可以显示编译好内核后所有在内核中的符号,模块中的要另行查看。
4.通过nm vmlinux也可以查看内核符号列表
可以显示编译好内核后所有在内核中的符号,模块中的要另行查看。
5.通过nm module_name可以查看模块的符号列表
但是得到是相对地址,只有加载后才会分配绝对地址。比如:e1000模块,如果e1000中的符号经过EXPORT_SYMBOL处理,等加载后,我们可以通过more /boot/System.map和nm vmlinux命令查看到,但是没有EXPORT_SYMBOL的,我目前不知道怎么查看。
另个试验:
1.验证EXPORT_SYMBOL
模块hello.c代码如下:
      
1 #include <linux/module.h>
      2 #include <linux/kernel.h>
      3
      4 static int __init a_init_module(void)
      5 {
      6     unsigned long *__kcrctab_per_cpu__hrtimer_bases = 0xc02678b4;
      7     unsigned char *__kstrtab_per_cpu__hrtimer_bases = 0xc026926b;
      8     struct kernel_symbol *__ksymtab_per_cpu__hrtimer_bases = 0xc0265018;
      9
     10     printk("__kcrctab_per_cpu__hrtimer_bases = %08x\n", *__kcrctab_per_cpu__hrtimer_bases);
     11     printk("__kstrtab_per_cpu__hrtimer_bases = %s\n", __kstrtab_per_cpu__hrtimer_bases);
     12     printk("__ksymtab_per_cpu__hrtimer_bases value = %08x, name = %s\n", __ksymtab_per_cpu__hrtimer_bases->value,\
     13     __ksymtab_per_cpu__hrtimer_bases->name);
     14
     15     return 0;
     16 }
     17
     18 static void __exit a_cleanup_module(void)
     19 {
     20     printk("Bye, Bye\n");
     21 }
      22 module_init(a_init_module);
     23 module_exit(a_cleanup_module);
      
     Makefile配置文件如下:
     
 1 #
      2 # Makefile for hello.c file
      3 #
      4 KDIR:=/lib/modules/$(shell uname -r)/build
      5
      6 obj-m:=hello.o
      7
      8 default:
      9     $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
     10 clean:
     11     $(RM) .*.cmd *.mod.c *.o *.ko -r .tmp*
 
     make; insmod hello.ko之后通过dmesg的运行结果:
__kcrctab_per_cpu__hrtimer_bases = 1ac19564
__kstrtab_per_cpu__hrtimer_bases = per_cpu__hrtimer_bases
__ksymtab_per_cpu__hrtimer_bases value = c0279ea0, name = per_cpu__hrtimer_bases
通过nm vmlinux | grep per_cpu__hrtimer_bases我们可以看到如下的对应关系:
1ac19564 A __crc_per_cpu__hrtimer_bases
c02678b4 r __kcrctab_per_cpu__hrtimer_bases
c026926b r __kstrtab_per_cpu__hrtimer_bases
c0265018 r __ksymtab_per_cpu__hrtimer_bases
c0279ea0 d per_cpu__hrtimer_bases
对比如上两列数据。
本实验只是为了验证一下EXPROT_SYMBOL.

2.1.EXPORT_SYMBOL和EXPORT_SYMBOL_GPL的区别
模块1:hello.c
     
1 #include <linux/module.h>
      2 #include <linux/kernel.h>
      3
      4 void function1(void)
      5 {
      6     printk("hello wold\n");
      7 }
      8 EXPORT_SYMBOL(function1);
      9
     10 void function2(void)
     11 {
     12     printk("hello wold again\n");
     13 }
     14 EXPORT_SYMBOL_GPL(function2);
     15
     16
     17 static int __init a_init_module(void)
     18 {
     19     return 0;
     20 }
     21
     22 static void __exit a_cleanup_module(void)
     23 {
     24     printk("<1>Bye, Bye\n");
     25
     26 }
     27
     28 module_init(a_init_module);
     29 module_exit(a_cleanup_module);
 
模块2:hello2.c
   
 1 #include <linux/module.h>
      2 #include <linux/kernel.h>
      3
      4 //MODULE_LICENSE("GPL");
      5
      6 static int __init a_init_module(void)
      7 {
      8     function1();
      9 //    function2();
     10     return 0;
     11 }
     12
     13 static void __exit a_cleanup_module(void)
     14 {
     15     printk("<1>Bye, Bye\n");
     16
     17 }
     18
     19 module_init(a_init_module);
     20 module_exit(a_cleanup_module);
     
    首先编译后两个模块:hello.ko, hello2.ko
    A.在hello2.c中注释掉MODULE_LICENSE("GPL")和function2()两行,先insmod hello.ko然后insmod hello2.ko,一切正常。
    B.先insmod hello2.ko然后insmod hello.ko,会有出错信息,通过dmesg查看显示如下:hello2: Unknown symbol function1
    C.在hello2.c中打开function2(),先insmod hello.ko然后insmod hello2.ko,模块hello2.ko无法加载,显示如下信息:insmod: error inserting 'hello2.ko': -1 File exists,通过dmesg查看显示如下:hello2: Unknown symbol function2。在hello2.c中打开MODULE_LICENSE("GPL")或者用MODULE_LICENSE("Dual BSD/GPL"),先insmod hello.ko然后insmod hello2.ko,一切正常。

所以说EXPORT_SYMBOL_GPL的符号必须要用MODULE_LICENSE("GPL")或者用MODULE_LICENSE("Dual BSD/GPL")之后才能在模块中引用。而且MODULE_LICENSE("char")中的char不可以是任意字符,否则错误和没有MODULE_LICENSE效果一样。
    D.没有看MODULE_LICENSE内核代码,下一步去研读代码。

分享到:
评论

相关推荐

    获取Linux内核未导出符号的几种方式

    只有在内核中使用EXPORT_SYMBOL或EXPORT_SYMBOL_GPL导出的符号才能在内核模块中直接使用。然而,内核并没有导出所有的符号。例如,在3.8.0的内核中,do_page_fault没有被导出。  而我的内核模块中需要使用do_page...

    嵌入式系统/ARM技术中的Linux内核中EXPORT_SYMBOL的用法

    这个头文件包含了`EXPORT_SYMBOL`宏定义和其他与模块相关的函数声明,确保编译器知道如何处理这个指令。 ```c #include ``` 2. **定义函数**:然后,你需要定义你想导出的函数。这个函数应该按照正常的C语言函数...

    linux模块间函数调用通讯

    - **EXPORT_SYMBOL_GPL**: 与EXPORT_SYMBOL类似,但仅允许GPL许可证下的模块调用导出的符号。这种方式适用于希望限制使用范围的情况。 示例: ```c EXPORT_SYMBOL_GPL(my_function_gpl); ``` 为了确保符号正确...

    the_platinum_searcher:与ack和the_silver_searcher(ag)类似的代码搜索工具。 它支持多种平台和多种编码

    白金搜寻者 一个类似于ack和the_silver_searcher(ag)代码搜索工具。 它支持多种平台和多种编码。 特征 它比ack快3到5倍地搜索代码。 它搜索代码的速度与the_silver_searcher(ag)一样快。...ag EXPORT_SYMBOL_GPL 1

    linux 内核模块

    使用`EXPORT_SYMBOL`或`EXPORT_SYMBOL_GPL`宏来标记要导出的符号,以便其他模块可以使用。 二、模块编写实例 一个简单的内核模块示例可能如下: ```c #include #include MODULE_LICENSE("GPL"); MODULE_AUTHOR...

    Linux内核模块开发常用内核接口

    - **`EXPORT_SYMBOL_GPL()`**:此宏与前者相似,但限制了导出仅对GPL许可证下的模块可用。 ##### **5. 模块信息** ```c MODULE_AUTHOR(author); MODULE_DESCRIPTION(description); MODULE_VERSION(version_string)...

    驱动-A53 .pptx

    EXPORT_SYMBOL(symbol_name); ``` **模块的编译和装载** 编译内核模块需要内核头文件,并使用如`make`命令构建。装载模块使用`insmod`,卸载使用`rmmod`,查看模块信息用`modinfo`,搜索模块用`modprobe`。 **设备...

    linux_module_dependencies:提供和使用导出符号的两个简单驱动程序

    像往常一样使用 EXPORT_GPL_SYMBOL 或 EXPORT_SYMBOL 导出您的符号。 正常构建您的提供程序模块 - 并查看 Module.symvers 文件,因为我们将取决于它导出的内容 - Makefile 包含神奇的部分。 你的依赖模块现在需要...

    编写简单的内核模块.pdf

    - 解决问题:为使模块能访问`my_variable`,需要在内核源码中使用`EXPORT_SYMBOL(my_variable)`导出该变量。 5. **模块调试**: - 错误处理:当模块加载失败时,系统会给出错误信息,如"Unknown symbol in module...

    LINUX内核模块编程

    2. `EXPORT_SYMBOL`和`EXPORT_SYMBOL_GPL`:这两个宏用于导出内核符号,使得其他模块可以使用。 3. `device`和`driver`结构:用于设备驱动编程,表示硬件设备和与其关联的驱动程序。 4. `request_module`和`try_...

    linux驱动开发

    通过`EXPORT_SYMBOL`或`EXPORT_SYMBOL_GPL`宏,可以将符号添加到内核符号表,增强模块间的协作能力。使用计数机制则保证了模块的稳定性和资源的安全回收。 #### 编译与装载 模块的编译通常需要特定的工具链和内核...

    Unreliable Guide To Hacking The Linux Kernel

    - **EXPORT_SYMBOL_GPL()**:`#include &lt;linux/module.h&gt;`,与EXPORT_SYMBOL()相似,但限制只能由GPL许可的模块使用。 #### 10. 常规和约定 - **双链表操作(Double-linked lists)**:`#include &lt;linux/list.h&gt;`,...

    Linux Device Driver Introduction

    - **导出符号**:为了使其他模块能够访问特定函数,可以使用`EXPORT_SYMBOL()`宏进行声明。例如,下面的代码展示了如何导出`my_fun`函数供其他模块使用: ```c int my_fun(wlandevice_t *wlandev) { // 函数体......

    linux kernel 2.4和 2.6 的驱动编写区别

    6. **符号导出**:2.6内核默认不导出所有符号,需要显式使用`EXPORT_SYMBOL`,而2.4内核默认导出所有符号,除非使用`EXPORT_NO_SYMBOLS`。 7. **内核版本检查**:在2.6内核中,多个文件包含`&lt;linux/module.h&gt;`时...

    Linux2.6的内核移植资料

    2.6内核中,模块的许可证声明方式为MODULE_LICENSE("DualBSD/GPL"),与2.4内核中的MODULE_LICENSE("GPL")有所不同。 3. 模块参数的定义方式。模块参数在2.6内核中使用module_param宏声明,同时提供了module_param_...

    Linux内核设备驱动之Linux内核模块加载机制笔记整理

    `EXPORT_SYMBOL`和`EXPORT_SYMBOL_GPL`宏用于将内核模块的函数或变量导出到内核的符号表。前者可以被任何其他模块或内核代码使用,而后者则限制为只允许遵循GPL许可证的代码访问。这样做的目的是保护代码的使用权限...

Global site tag (gtag.js) - Google Analytics