Linux设备驱动开发详解-第4章(三)-导出符号
2011-10-24 17:15
309 查看
Linux设备驱动开发详解-第4章(三)-导出符号
EXPORT_SYMBOL只出现在2.6内核中,在2.4内核默认的非static函数和变量都会自动导入到kernel 空间的, 都不用EXPORT_SYMBOL() 做标记的。
2.6就必须用EXPORT_SYMBOL()来导出来(因为2.6默认不到处所有的符号)。
这里要和System.map做一下对比:
System.map 中的是连接时的函数地址。连接完成以后,在2.6内核运行过程中,是不知道哪个符号在哪个地址的。
EXPORT_SYMBOL 的符号,是把这些符号和对应的地址保存起来,在内核运行的过程中,可以找到这些符号对应的地址。而模块在加载过程中,其本质就是能动态连接到内核,如果在模块中引用了内核或其它模块的符号,就要EXPORT_SYMBOL这些符号,这样才能找到对应的地址连接。
2 使用方法
第一、在模块函数定义之后使用EXPORT_SYMBOL(函数名)
第二、在掉用该函数的模块中使用extern对之声明
第三、首先加载定义该函数的模块,再加载调用该函数的模块
另外,在编译调用某导出函数的模块时,往往会有WARNING: "****" [**********] undefined!
使用dmesg命令后会看到相同的信息。开始我以为只要有这个错误就不能加载模块,后来上网查了一下,发现这主要是因为在编译连接的时候还没有和内核打交道,当然找不到symbol了,但是由于你生成的是一个内核模块,所以LD不提示error,而是给出一个warning,寄希望于在insmod的时候,内核能够把这个symbol连接上。
第一个是export_symb.c,这个模块是一个导出整数加、减运算函数符号的内核模块的例子(这些导出符号没有实际意义,只是为了演示)。
第二个模块是import_ symb.c,这个模块调用export_symb的导出符号。
3.1 export_symb.c模块
(1)export_symb.c文件
(2)Makefile文件
(3)编译和加载
从“/proc/kallsyms”文件中找出add_integar、sub_integar 相关信息:
(2)Makefile文件
(3)编译和加载
(2)import_symb需要调用export_symb,所以加载import_symb之前先要加载export_symb模块。
(3)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这些符号,这样才能找到对应的地址连接。
2 使用方法
第一、在模块函数定义之后使用EXPORT_SYMBOL(函数名)
第二、在掉用该函数的模块中使用extern对之声明
第三、首先加载定义该函数的模块,再加载调用该函数的模块
另外,在编译调用某导出函数的模块时,往往会有WARNING: "****" [**********] undefined!
使用dmesg命令后会看到相同的信息。开始我以为只要有这个错误就不能加载模块,后来上网查了一下,发现这主要是因为在编译连接的时候还没有和内核打交道,当然找不到symbol了,但是由于你生成的是一个内核模块,所以LD不提示error,而是给出一个warning,寄希望于在insmod的时候,内核能够把这个symbol连接上。
3 实例验证
本文将编写两个模块来验证导出符号。第一个是export_symb.c,这个模块是一个导出整数加、减运算函数符号的内核模块的例子(这些导出符号没有实际意义,只是为了演示)。
第二个模块是import_ symb.c,这个模块调用export_symb的导出符号。
3.1 export_symb.c模块
(1)export_symb.c文件
/*====================================================================== A simple kernel module to introduce export symbol The initial developer of the original code is Baohua Song <author@linuxdriver.cn>. All Rights Reserved. ======================================================================*/ #include <linux/init.h> #include<linux/kernel.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); int add_integar(int a,int b) { printk(KERN_INFO "add_integar\n"); return a+b; } int sub_integar(int a,int b) { printk(KERN_INFO "sub_integar\n"); return a-b; } EXPORT_SYMBOL(add_integar); EXPORT_SYMBOL(sub_integar); static int __init export_symb_init(void) { printk(KERN_INFO "export_symb,Init!\n"); return 0; } static void __exit export_symb_exit(void) { printk(KERN_INFO "export_symb,Exit!\n"); } module_init(export_symb_init); module_exit(export_symb_exit); MODULE_AUTHOR("Minghua"); MODULE_DESCRIPTION("export_symb export"); MODULE_ALIAS("export_symb ");
(2)Makefile文件
#ifneq ($(KERNELRELEASE),) obj-m := import_symb.o #else KERNELDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules #endif clean: rm -f*.ko *.mod.c *.mod.o *.o *.markers *.order *.symvers
(3)编译和加载
[root@localhost export_symb]# make [root@localhost export_symb]# insmod export_symb.ko [root@localhost export_symb]# dmesg | tail -2 export_symb,Exit! export_symb,Init!
从“/proc/kallsyms”文件中找出add_integar、sub_integar 相关信息:
[root@localhost export_symb]# cat /proc/kallsyms | grep integar f7fde0bc r __ksymtab_sub_integar [export_symb] f7fde0cc r __kstrtab_sub_integar [export_symb] f7fde0c4 r __ksymtab_add_integar [export_symb] f7fde0d8 r __kstrtab_add_integar [export_symb] f7fde01e T add_integar [export_symb] f7fde000 T sub_integar [export_symb]
3.2 import_ symb.c模块
(1)import _symb.c文件/*====================================================================== A simple kernel module to introduce export symbol The initial developer of the original code is Baohua Song <author@linuxdriver.cn>. All Rights Reserved. ======================================================================*/ #include<linux/init.h> #include<linux/kernel.h> #include<linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); extern int add_integar(int a,int b); extern int sub_integar(int a,int b); static void func2(void) { int temp = 0; temp = add_integar(10,5); printk(KERN_INFO "add_integar(10,5) = %d \n", temp); temp = sub_integar(10,5); printk(KERN_INFO "sub_integar(10,5) = %d \n",temp); temp = sub_integar(10,5); printk(KERN_INFO "sub_integar(10,5) = %d \n",temp); } static int __init import_symb_init(void) { printk(KERN_INFO "Import_symb,Init!\n"); func2(); return 0; } static void __exit import_symb_exit(void) { printk(KERN_INFO "Import_symb,Exit!\n"); } module_init(import_symb_init); module_exit(import_symb_exit); MODULE_AUTHOR("Minghua"); MODULE_DESCRIPTION("import_symb call"); MODULE_ALIAS("import_symb ");
(2)Makefile文件
#ifneq ($(KERNELRELEASE),) obj-m := import_symb.o #else KERNELDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules #endif clean: rm -f *.ko *.mod.c *.mod.o *.o *.markers *.order *.symvers
(3)编译和加载
[root@localhost import_symb]# make [root@localhost import_symb]# insmod import_symb.ko [root@localhost import_symb]# dmesg | tail -5 Import_symb,Init! add_integar add_integar(10,5) = 15 sub_integar sub_integar(10,5) = 5
4 扩展
(1)本例中因为export_symb是被调用者,所以当其被调用时,export_symb不能被卸载,只有在未被调用的情况下才能卸载。(2)import_symb需要调用export_symb,所以加载import_symb之前先要加载export_symb模块。
(3)EXPORT_SYMBOL在内核中是经常出现的。
相关文章推荐
- Linux设备驱动开发详解-第4章(二)-模块参数
- Linux设备驱动开发详解-Note(8)---Linux 内核模块(2)
- Linux设备驱动开发详解-Note(9)--- Linux 文件系统与设备文件系统(1)
- Linux设备驱动开发详解-Note(16)---Linux 设备驱动中的阻塞与非阻塞 I/O(1)
- linux 设备驱动开发详解 code (1)
- Linux设备驱动开发详解-Note(9) --- 环境变量的增加/修改/获取-linux
- 《Linux 设备驱动开发详解》--Linux驱动概述及开发环境
- Linux设备驱动开发详解-Note(2)---设备驱动概述(2)
- Linux设备驱动开发详解-Note(10)--- Linux 文件系统与设备文件系统(2)
- Linux设备驱动开发详解-Note(18)---Linux 设备驱动中的异步通知与异步 I/O(1)
- linux设备驱动开发详解 笔记
- Driver:搭建linux驱动开发环境、内核驱动开发基础、导出符号、打印优先级
- Linux设备驱动开发详解-Note(17)---Linux 设备驱动中的阻塞与非阻塞 I/O(2)
- linux 设备驱动开发详解 code (2)
- Linux设备驱动开发详解--笔记3--Linux内核及内核编程
- Linux设备驱动开发详解--笔记10--中断与时钟
- linux驱动开发--导出内核符号
- linux 设备驱动开发详解 code (3)
- Linux设备驱动开发详解-Note(9)--- Linux 文件系统与设备文件系统(1)
- linux 设备驱动开发详解 code (4)