EXPORT_SYMBOL宏的使用时出现在Linux-2.6之后,在Linux-2.4内核中,默认的非static 函数和变量都会自动导入到kernel 空间, 都不用EXPORT_SYMBOL() 做标记的。
然后Linux-2.6之后默认不导出所有的符号,所以使用EXPORT_SYMBOL() 做标记。
二、EXPORT_SYMBOL宏的作用
三、EXPORT_SYMBOL使用方法
1.在模块函数定义之后使用EXPORT_SYMBOL(函数名)
2.在调用该函数的模块中使用extern对要使用的符号或者函数进行声明
3.首先加载定义该函数的模块,再加载调用该函数的模块
四、例子
1、编写源代码文件
1)module_a.c
#include <linux/init.h> //所有模块都必须包含的头文件
#include <linux/module.h> //一些宏定义,例如这里的KERN_INFO
#include <linux/kernel.h>
#define DRIVER_AUTHOR "xz@vi-chip.com.cn"
#define DRIVER_DESC "A sample driver"
int func1(void)
{
printk("In Func: %s...\n",__func__);
return 0;
}
// Export symbol func1
EXPORT_SYMBOL(func1);
static int __init hello_init(void)
{
printk(KERN_INFO "module1 Hello world!\n");//前面的宏表示打印的级别
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "module1 hello exit!\n");
}
module_init(hello_init);//用宏来指定入口,加载模块时里面的加载函数会被调用
module_exit(hello_exit);
//模块的许可证
MODULE_LICENSE("GPL");
//模块的作者
MODULE_AUTHOR(DRIVER_AUTHOR);
//模块的描述
MODULE_DESCRIPTION(DRIVER_DESC);
2)module_b.c
#include <linux/init.h> //所有模块都必须包含的头文件
#include <linux/module.h> //一些宏定义,例如这里的KERN_INFO
#include <linux/kernel.h>
#define DRIVER_AUTHOR "xz@vi-chip.com.cn"
#define DRIVER_DESC "A sample driver"
extern int func1(void);//导出符号外部函数声明
static int func2(void)
{
func1();
printk("In Func: %s...\n",__func__);
return 0;
}
static int __init hello_init(void)
{
printk(KERN_INFO "module2 Hello world!\n");//前面的宏表示打印的级别
func2();
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "module2 hello exit!\n");
}
module_init(hello_init);//用宏来指定入口,加载模块时里面的加载函数会被调用
module_exit(hello_exit);
//模块的许可证
MODULE_LICENSE("GPL");
//模块的作者
MODULE_AUTHOR(DRIVER_AUTHOR);
//模块的描述
MODULE_DESCRIPTION(DRIVER_DESC);
2、编写Makefile
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
else
obj-m := module_a.o module_b.o
endif
五、编译内核模块
执行make all 或make
六、安装内核模块
1、先安装module_a.ko
2、再安装module_b.ko
七、查看输出信息
dmesg
[162797.214107] module1 Hello world!
[162802.170616] module2 Hello world!
[162802.170622] In Func: func1...
[162802.170624] In Func: func2...
八、卸载内核模块
1、先卸载sudo rmmod module_b
2、再卸载sudo rmmod module_a
完毕。