符号导出EXPORT_SYMBOL
在写linux驱动程序的过程中遇到一个模块中编写的函数,或者变量需要在另一个模块中使用的时候就可以用符号导出EXPORT_SYMBOL。在Linux内核源码目录下有一个文件Module.symvers,该文件内就存放的linux内核中导出的符号。
下面的代码是使用方法,首先是模块A,模块A中有一个变量num,和一个函数print_hello需要在模块B中使用,所以需要将模块A中的这两个导出。
// 模块A
#include <linux/module.h>
static int num = 100;
static void print_hello(void)
{
printk("hello\r\n");
}
static int __init symbol_init(void)
{
printk("export symbol\r\n");
return 0;
}
static void __exit symbol_exit(void)
{
printk("exit\r\n");
}
module_init(symbol_init);
module_exit(symbol_exit);
EXPORT_SYMBOL(num);
EXPORT_SYMBOL(print_hello);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chen");
模块A的Makefile
ifneq ($(KERNELRELEASE,))
obj-m:=a.o
else
KERNEL_DIR:=/lib/modules/$(shell uname -r)/build
CURRENT_DIR:=$(shell pwd)
ccflags-y:=-std=gnu99 -Wno-declaration-after-statement
all:
$(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) modules
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) clean
endif
接着是模块B的代码,首先在B模块编译之前,需要将模块A编译后目录下生成的的Module.symvers文件拷贝到模块B目录下,这样模块B中才能找到需要的模块A导出的符号。
// 模块B
#include <linux/module.h>
extern int num;
extern void print_hello(void);
static int __init use_init(void)
{
print_hello();
return 0;
}
static void __exit use_exit(void)
{
printk("num = %d\r\n",num);
}
module_init(use_init);
module_exit(use_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chen");
模块B的Makefile通模块A,只需改obj-m后面的名字。
接下来就是编译模块B。
这里一定要注意顺序,首先是先将模块A编译,因为模块A编译后目录下的Module.symvers文件中才有导出的符号,然后再将该文件拷贝到 模块B目录下,有这个文件后编译的模块B才不会报错。
接着就是加载模块,这里也一定要有顺序,应当先加载A模块再加载B模块,写在也是先写在B模块再写在A模块,顺序反了会报错的。