博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux设备驱动开发详解-第4章(三)-导出符号
阅读量:3512 次
发布时间:2019-05-20

本文共 4550 字,大约阅读时间需要 15 分钟。

Linux设备驱动开发详解-第4章(三)-导出符号

 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    
. All Rights Reserved.======================================================================*/#include
#include
#include
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#elseKERNELDIR := /lib/modules/$(shell uname -r)/buildPWD := $(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 -2export_symb,Exit!export_symb,Init!

从“/proc/kallsyms”文件中找出add_integar、sub_integar 相关信息:

[root@localhost export_symb]# cat /proc/kallsyms | grep integarf7fde0bc 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    
. All Rights Reserved.======================================================================*/#include
#include
#include
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#elseKERNELDIR := /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)default:	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules#endifclean:	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 -5Import_symb,Init!add_integaradd_integar(10,5) =  15 sub_integarsub_integar(10,5) =  5

4 扩展

       (1)本例中因为export_symb是被调用者,所以当其被调用时,export_symb不能被卸载,只有在未被调用的情况下才能卸载。

       (2)import_symb需要调用export_symb,所以加载import_symb之前先要加载export_symb模块。
       (3)EXPORT_SYMBOL在内核中是经常出现的。

转载地址:http://oifqj.baihongyu.com/

你可能感兴趣的文章
可调谐半导体激光器的窄线宽测试及压缩
查看>>
matlab中 %d,%f,%c,%s
查看>>
常见的光纤接头汇总
查看>>
半导体激光器—问题整理(二)
查看>>
科研日记7.31
查看>>
问题整理3
查看>>
zemax仿真二向色镜
查看>>
stm32单片机编程时extern的用法
查看>>
UART4和5的问题
查看>>
Spring框架中在并发访问时的线程安全性
查看>>
网站部署
查看>>
什么情况下会发生栈内存溢出。
查看>>
何为去中心化
查看>>
本地缓存的优缺点
查看>>
缓存一致性:写策略
查看>>
Cache一致性:MESI
查看>>
缓存一致性:写未命中
查看>>
为什么用中间位作为组索引
查看>>
缓存:局部性
查看>>
mysql原理:b+树索引
查看>>