使用EXPORT_SYMBOL

在Linux内核里,我们编写驱动程序时,如果遇到的驱动太大,需要在各个模块之间共享一些变量或函数等,此时就需要用到内核里的EXPORT_SYMBOL宏了,其在include/linux/export.h文件中定义,而最常用的有如下两个:
#define EXPORT_SYMBOL(sym)                                      \
        __EXPORT_SYMBOL(sym, "")
#define EXPORT_SYMBOL_GPL(sym)                                  \
        __EXPORT_SYMBOL(sym, "_gpl")
       其中,多加了_GPL尾的量需要在使用MODULE_LICENSE()宏定义为GPL协议的模块里才能引用,不然加载驱动时会有类似Unknown symbol export_orig_gpl (err 0)的提示(该提示取自下面的例子),当然,模块之间也需要有加载先后顺序,其中EXPORT的模块需先加载,extern的后加载,不然也会有类似如上的提示。
       这里的例子会用到两个源码文件,作为export的文件名为export_orig.c,作为extern的文件名为export_symbol_example.c,相应的源码如下:
       export_orig.c:
#include <linux/kernel.h>
#include <linux/module.h>
static int export_orig_normal;
static int export_orig_gpl;
EXPORT_SYMBOL(export_orig_normal);
EXPORT_SYMBOL_GPL(export_orig_gpl);
static __init int export_orig_init(void)
{
        printk("Enter %s\n", __func__);
        export_orig_normal = 10;
        export_orig_gpl = 20;
        return 0;
}
static __exit void export_orig_exit(void)
{
        printk("Bye export_orig!\n");
}
module_init(export_orig_init);
module_exit(export_orig_exit);
       export_symbol_example.c:
#include <linux/kernel.h>
#include <linux/module.h>
extern int export_orig_normal;
extern int export_orig_gpl;
MODULE_LICENSE("GPL");
static __init int export_symbol_example_init(void)
{
        printk("Enter %s\n", __func__);
        printk("export_orig_normal=%d\n", export_orig_normal);
        printk("export_orig_gpl=%d\n", export_orig_gpl);
        return 0;
}
static __exit void export_symbol_example_exit(void)
{
        printk("Bye export_symbol example!\n");
}
module_init(export_symbol_example_init);
module_exit(export_symbol_example_exit);
       相应的Makefile内容如下:
obj-m += export_symbol_example.o export_orig.o
CUR_PATH:=$(shell pwd)
LINUX_KERNEL_PATH:=/home/xinu/linux-3.13.6
all:
        make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) modules
clean:
        make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) clean
       接下来就可以make再insmod测试下了,注意模块间的加载顺序,建议做如下测试:
       1.先加载export_symbol_example.ko,再看看dmesg的输出;
       2.去掉export_symbol_example.c里的MODULE_LICENSE(“GPL”);再测试下;
       测试完后,现在可以清楚了解到整个export symbol与extern symbol的使用了吧,当然也不仅仅在变量,也可以export函数啊,自已测试玩玩看吧。

评论

此博客中的热门博文

I/O映射之I/O端口

通过Netlink检测网线插拔

使用seq_file