linux 内核模块编程之内核符号导出(五)
2016-01-07 20:29
573 查看
/proc/kallsyms 记录了内核中所有导出的符号的名字与地址
我们需要编译2个内核模块,然后其中一个内核模块去调用另一个内核模块中的函数
hello.c代码如下
从这可以看出我们的hello.c中调用了2个函数 add_integar和 sub_integer,这2个函数我们在另一个模块中实现
calculate.c的代码如下
calculate.c对应的makefile 如下
分别编译完之后我们会得到一个hello.ko文件和calculate.ko文件
然后我们就可以将我们的模块拷贝到我们的开发板上运行测试了。
2个模块我们得先安装calculate.ko ,不然的话hello.ko会因为找不到函数的实现而报错,测试结果如下
EXPORT_SYMBOL_GPL(符号名)
其中EXPORT_SYMBOL_GPL只能用于包含GPL许可证的模块
insmod hello.ko
disagrees about version of symbol struct_module
insmod: error inserting 'hello.ko': -1 Invalid module format
2、确保编译内核模块时,所依赖的内核代码版本等于当前正在运行的内核,可通过uname -r查看当前运行的内核版本
有一种投机取巧的方式,就是修改/home/grb/grb/arm/linux-2.6.38/Makefile 文件中的版本号,如下
前面几行就是他的版本号,这种方法很容易出问题,所以不推荐这种方法。
内核打印优先级
在<linux/kernel.h>中定义了8种记录级别。按照优先级别递减的顺序分别是:
KERN_EMERG "<0>"
用于紧急消息,常常是那些崩溃前的消息。
KERN_ALERT "<1>"
需要立刻行动的消息
KERN_CRIT "<2>"
严重情况
KERN_ERR "<3>"
错误情况
如果没有指定消息的级别,printk()会使用默认的DEFAULT_MESSAGE_LOGLEVEL,他是一个在kernel/printk.c中定义的整数
我们需要编译2个内核模块,然后其中一个内核模块去调用另一个内核模块中的函数
hello.c代码如下
#include <linux/module.h> #include <linux/init.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Xie"); MODULE_DESCRIPTION("Hello World Module"); MODULE_ALIAS("a simplest module"); extern int add_integar(int a, int b); extern int sub_integer(int a, int b); static int __init hello_init() { int res = add_integar(1, 2); printk("add[%d]\n",res); return 0; } static void __exit hello_exit() { int res = sub_integer(2, 1); printk("sub[%d]\n",res); } module_init(hello_init); module_exit(hello_exit);
从这可以看出我们的hello.c中调用了2个函数 add_integar和 sub_integer,这2个函数我们在另一个模块中实现
calculate.c的代码如下
#include <linux/module.h> #include <linux/init.h> MODULE_LICENSE("GPL"); int add_integar(int a, int b) { return a+b; } int sub_integer(int a, int b) { return a-b; } static int __init sym_init() { return 0; } static void __exit sym_exit() { } module_init(sym_init); module_exit(sym_exit); EXPORT_SYMBOL(add_integar);//导出函数,供hello.c调用 EXPORT_SYMBOL(sub_integer);//导出函数,供hello.c调用
calculate.c对应的makefile 如下
ifneq ($(KERNELRELEASE),) obj-m := calculate.o else KERNELDIR ?= /home/grb/grb/arm/linux-2.6.38/ PWD := $(shell pwd) all: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers *~ *.order endif
分别编译完之后我们会得到一个hello.ko文件和calculate.ko文件
然后我们就可以将我们的模块拷贝到我们的开发板上运行测试了。
2个模块我们得先安装calculate.ko ,不然的话hello.ko会因为找不到函数的实现而报错,测试结果如下
内核符号导出的使用
EXPORT_SYMBOL(符号名)EXPORT_SYMBOL_GPL(符号名)
其中EXPORT_SYMBOL_GPL只能用于包含GPL许可证的模块
常见问题:版本不匹配
内核模块的版本由其所依赖的内核代码版本所决定,在加载内核模块时,insmod程序会将内核模块的版本与当前正在运行的内核版本比较,如果不一致,就会出现下面的错误:insmod hello.ko
disagrees about version of symbol struct_module
insmod: error inserting 'hello.ko': -1 Invalid module format
解决方法:
1、使用modprobe --force-modversion强行插入(不推荐)2、确保编译内核模块时,所依赖的内核代码版本等于当前正在运行的内核,可通过uname -r查看当前运行的内核版本
有一种投机取巧的方式,就是修改/home/grb/grb/arm/linux-2.6.38/Makefile 文件中的版本号,如下
前面几行就是他的版本号,这种方法很容易出问题,所以不推荐这种方法。
内核打印优先级
在<linux/kernel.h>中定义了8种记录级别。按照优先级别递减的顺序分别是:
KERN_EMERG "<0>"
用于紧急消息,常常是那些崩溃前的消息。
KERN_ALERT "<1>"
需要立刻行动的消息
KERN_CRIT "<2>"
严重情况
KERN_ERR "<3>"
错误情况
如果没有指定消息的级别,printk()会使用默认的DEFAULT_MESSAGE_LOGLEVEL,他是一个在kernel/printk.c中定义的整数
相关文章推荐
- Linux socket 初步
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- 基于 Linux 集群环境上 GPFS 的问题诊断