EXPORT_SYMBOL宏定义原型:
#define EXPORT_SYMBOL(sym) \
__EXPORT_SYMBOL(sym, "")
其中__EXPORT_SYMBOL原型如下:
/* For every exported symbol, place a struct in the __ksymtab section */
#define __EXPORT_SYMBOL(sym, sec) \
extern typeof(sym) sym; \
__CRC_SYMBOL(sym, sec) \
static const char __kstrtab_##sym[] \
__attribute__((section("__ksymtab_strings"), aligned(1))) \
= MODULE_SYMBOL_PREFIX #sym; \
static const struct kernel_symbol __ksymtab_##sym \
__used \
__attribute__((section("__ksymtab" sec), unused)) \
= { (unsigned long)&sym, __kstrtab_##sym }
__EXPORT_SYMBOL宏定义主要有四个方面:
1.获取导出的符号的名称,以字符串表示
2.把获取到的以字符串表示的名称以及值放入,__ksymtab_+导出的符号为变量的struct kernel_symbol变量中;
3.在编译工程中,把struct kernel_symbol编译进入以"ksymtab"为开头的符号表中;
4.内核在加载模块时候先查找已经加载过的模块的符号表,如果不存在则继续加载模块
EXPORT_SYMBOL_GPL宏定义与EXPORT_SYMBOL宏定义差不多,不过是编译过程中和加载过程中把符号表加入了以"ksymtab_gpl"为区域的文件中或者内存中。
其中struct kernel_symbol函数原型定义如下:
struct kernel_symbol
{
unsigned long value;
const char *name;
};
从定义可以看出使用EXPORT_SYMBOL函数就是把导出的符号以符号值+符号的字符串表示的形式表示的;
EXPORT_SYMBOL函数的使用:
#include
#include
static inline int
module_a_init_func(void)
{
printk("this is module a init func\n");
return 0;
}
static inline void
module_a_exit_func(void)
{
printk("this is module a exit func\n");
}
static inline int __init
module_a_init(void)
{
printk("this is module a init\n");
return module_a_init_func();
}
static inline void __exit
module_a_exit(void)
{
printk("this is module a exit\n");
module_a_exit_func();
}
EXPORT_SYMBOL(module_a_init_func);
EXPORT_SYMBOL(module_a_exit_func);
module_init(module_a_init);
module_exit(module_a_exit);
modulea’s Makefile
KERN_DIR = /lib/modules/`uname -r`/build/
obj-m := modulea.o
all:
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
make -C $(KERN_DIR) M=$(shell pwd) modules clean
#include
#include
extern int
module_a_init_func(void);
extern void
module_a_exit_func(void);
static inline int __init
module_b_init(void)
{
return module_a_init_func();
}
static inline int __exit
module_b_exit(void)
{
module_a_exit_func();
}
module_init(module_b_init);
module_exit(module_b_exit);
moduleb’s Makefile
KERN_DIR = /lib/modules/`uname -r`/build/
obj-m := moduleb.o
KBUILD_EXTRA_SYMBOLS+=/usr/src/linux-2.6.39/driver/export/modulea/Module.symvers
export KBUILD_EXTRA_SYMBOLS
all:
make -C ../modulea/
make -C $(KERN_DIR) M=$(shell pwd) modules
clean:
make -C $(KERN_DIR) M=$(shell pwd) modules clean
其中,“KBUILD_EXTRA_SYMBOLS+=/usr/src/linux-2.6.39/driver/export/modulea/Module.symvers“的模块A的Modules.symvers路径是绝对路径,不能是相对路径;相对路径会发生如下问题:
//都能够编译成.ko文件:
root@ubuntu:/usr/src/linux-2.6.39/driver/export/moduleb# make
make -C ../modulea/
make[1]: Entering directory `/usr/src/linux-2.6.39/driver/export/modulea'
make -C /lib/modules/`uname -r`/build/ M=/usr/src/linux-2.6.39/driver/export/modulea modules
make[2]: Entering directory `/usr/src/linux-headers-3.13.0-160-generic'
Building modules, stage 2.
MODPOST 1 modules
make[2]: Leaving directory `/usr/src/linux-headers-3.13.0-160-generic'
make[1]: Leaving directory `/usr/src/linux-2.6.39/driver/export/modulea'
make -C /lib/modules/`uname -r`/build/ M=/usr/src/linux-2.6.39/driver/export/moduleb modules
make[1]: Entering directory `/usr/src/linux-headers-3.13.0-160-generic'
CC [M] /usr/src/linux-2.6.39/driver/export/moduleb/moduleb.o
/usr/src/linux-2.6.39/driver/export/moduleb/moduleb.c: In function ‘module_b_exit’:
/usr/src/linux-2.6.39/driver/export/moduleb/moduleb.c:20:1: warning: no return statement in function returning non-void [-Wreturn-type]
}
^
In file included from /usr/src/linux-2.6.39/driver/export/moduleb/moduleb.c:1:0:
/usr/src/linux-2.6.39/driver/export/moduleb/moduleb.c: In function ‘__exittest’:
include/linux/init.h:303:4: warning: return from incompatible pointer type [enabled by default]
{ return exitfn; } \
^
/usr/src/linux-2.6.39/driver/export/moduleb/moduleb.c:23:1: note: in expansion of macro ‘module_exit’
module_exit(module_b_exit);
^
Building modules, stage 2.
MODPOST 1 modules
WARNING: "module_a_exit_func" [/usr/src/linux-2.6.39/driver/export/moduleb/moduleb.ko] undefined!
WARNING: "module_a_init_func" [/usr/src/linux-2.6.39/driver/export/moduleb/moduleb.ko] undefined!
CC /usr/src/linux-2.6.39/driver/export/moduleb/moduleb.mod.o
LD [M] /usr/src/linux-2.6.39/driver/export/moduleb/moduleb.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.13.0-160-generic'
root@ubuntu:/usr/src/linux-2.6.39/driver/export/moduleb# vim moduleb.c
#加载模块A成功,加载模块B失败;
root@ubuntu:/usr/src/linux-2.6.39/driver/export/moduleb# insmod ../modulea/modulea.ko
root@ubuntu:/usr/src/linux-2.6.39/driver/export/moduleb# insmod moduleb.ko
insmod: ERROR: could not insert module moduleb.ko: Invalid parameters