内核符号表可以分为“私有”和“公共”。平常所说的内核符号表指的是“公共内核符号表”。
我们知
道,驱动存在于内核空间,它的每一个函数每一个变量都会有对应的符号,这部分符号也可以称作内核符号,它们不导出的话就只能为自身所用,导出后就可以成为
公用,对于导出的那部分的内核符号就是我们常说的内核符号表。insmod的时候并不是所有的函数都得到内核符号表去寻找对应的符号,因为每一个驱动在自
己分配的空间里也会存在一份符号表,里面有关于这个驱动里使用到的变量以及函数的一些符号,驱动首先会在这里面找,如果发现某个符号没有了,那么就会去公
共内核符号表中搜索,搜素到了,则该模块加载成功,搜索不到则该模块加载失败。
对于2.4内核和2.6内核的内核符号表是有区别
的,2.4内核默认情况下模块中的非静态全局变量以及非静态函数在模块加载后会自动导出到内核符号表中,而2.6内核默认情况下是不会自动导出的,需要显
式调用宏EXPORT_SYMBOL才能导出。导出的符号前面一般标注有r标记。可以通过nm -l
xx.ko来查看某一个模块里的符号情况。或者通过查看内核符号表文件也行。对于2.4是:cat /proc/ksyms,对于2.6是:cat
/proc/kallsyms.
最后总结,对于一个模块来讲,如果仅依靠自身就可以实现自己的功能,那么可以不需要导出任何符号,只
有其他模块中需要使用到该模块提供的函数时,就必须要进行导出操作。
#export_symb.c
#include
#include
MODULE_LICENSE("Dual
BSD/GPL");
int add_integar(int a,int b)
{
return a+b;
}
int sub_integar(int a,int b)
{
return a-b;
}
EXPORT_SYMBOL(add_integar);
EXPORT_SYMBOL(sub_integar);
以下演示了,在模块a中导出内核符号, 在模块b中调用
基本步骤是在模块a中导出,加载模块a, 之后在调用模块b中包含.h文件,调用符号。
注: 内核符号表中的东西只能被内核空间程序访问。
1. 编写export_symb.c 导出内核符号: add_integar和sub_integar
/* export_symb.c */
#include
#include
#include "export_symb.h"
MODULE_LICENSE("Dual BSD/GPL");
int add_integar(int a, int b)
{
return a+b;
}
int sub_integar(int a, int b)
{
return a-b;
}
EXPORT_SYMBOL(add_integar);
EXPORT_SYMBOL(sub_integar);
2.编写export_symb.h ,提供add_integar和sub_integar调用的接口
/* export_symb.h */
int add_integar(int a,int b);
int sub_integar(int a,int b);
3.编写test.c,调用导出的内核符号函数 add_integar 和 sub_integar.
/* test.c */
#include
#include
#include "export_symb.h"
MODULE_LICENSE("Dual BSD/GPL");
static int integar_a = 5;
static int integar_b = 3;
static int integar_c = 0;
static int integar_d = 0;
static int integar_init(void)
{
integar_c = add_integar(integar_a,integar_b);
integar_d = sub_integar(integar_a,integar_b);
printk(KERN_INFO "integar_c:%d, integar_d:%d\n", integar_c, integar_d);
return 0;
}
static void integar_exit(void)
{
printk(KERN_INFO "integar exit");
}
module_init(integar_init);
module_exit(integar_exit);
module_param(integar_a, int, S_IRUGO);
module_param(integar_b, int, S_IRUGO);
MODULE_AUTHOR("fanpengfei");
MODULE_DESCRIPTION("A simple Module for testing module params");
MODULE_VERSION("V1.0");
4. 编写Makefile:
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /usr/src/kernels/$(shell uname -r)/
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.markers *.order *.symvers
.PHONY: modules clean
else
obj-m := export_symb.o test.o
endif
5.编译链接: make 生成export_symb.ko和test.ko
6.插入export_symb.ko
insmod export_symb.ko
7.查看内核符号: add_integar 和 sub_integar
[root@localhost proc]# cat kallsyms | grep integar
e0858040 r __ksymtab_sub_integar [export_symb]
e0858050 r __kstrtab_sub_integar [export_symb]
e0858048 r __ksymtab_add_integar [export_symb]
e085805c r __kstrtab_add_integar [export_symb]
e0858000 T add_integar [export_symb]
e085800d T sub_integar [export_symb]
8. 插入test.ko, 调用内核符号 add_integar和sub_integar
insmod test.ko
9. 查看日志,审查内核符号调用结果
[root@localhost proc]# tail -1 /var/log/messages
Jun 3 11:40:40 localhost kernel: integar_c:8, integar_d:2
10. 退出export_symb和test模块,因test模块调用export_symb模块,所以退出的顺序是先退出test模块,之后再退出export_symb模块
rmmod test
rmmod export_symb
阅读(671) | 评论(0) | 转发(0) |