一、问题整理
内核中两个模块,一个A,一个B,A模块中有操作函数,B模块要调用A模块的函数。
二、分析
这是一个驱动工程师常常遇见的一个问题,该问题似乎是模块符号导入问题,实现该功能比较简单,利用EXPORT_SYMBOL()即可。
1.哪些是符号?
这儿的符号主要指的是全局变量和函数linux socket函数详解,静态全局变量虽然也可以被另外一个模块访问到。
2.为何要导入符号?
↓Linux内核采用的是以模块化方式管理内核代码。内核中的每位模块互相之间是互相独立的qq linux,也就是说A模块的全局变量和函数,B模块是难以直接访问的。
有些时侯,我们写一些模块代码的时侯,发觉部份函数功能他人早已实现了,此时我们就想假如我们可以调用她们早已实现好的函数插口就好了。那怎么能够做到这点呢?
就靠符号导入了,也就是说你可以把你实现的函数插口和全局变量导入,以供其他模块使用。
在Linux内核的世界里,假若一个模块早已以静态的形式编译进的内核linux操作系统界面,这么它导入的符号还会出现在全局的内核符号表中。
在Ubuntu14.04系统中,Linux内核的全局符号表储存在以下文件:
/usr/src/linux-headers-3.2.0-29-generic-pae/Module.symvers
假如打开这个文件,可以发觉上面的内容就是:
Addr------->符号名------>模块名------>导出符号的宏
3.怎么导入符号?
Linux内核给我们提供了两个宏:
EXPORT_SYMBOL(name);
EXPORT_SYMBOL_GPL(name);
里面宏定义的任一个促使给定的符号在模块外可用;GPL版本的宏定义只能使符号对GPL许可的模块可用;符号必须在模块文件的全局部份输出,在任何函数之外,由于宏定义扩充成一个特殊用途的并被期望是全局存取的变量的申明。
4.模块编译时linux socket函数详解,怎样找寻使用的符号?5.案例演示
模块A导入全局变量global_var和函数show两个符号供模块B使用。
A模块
#include
#include
static int global_var = 100;
static void show(void)
{
printk("show(): global_var =%d n",global_var);
}
static int hello_init(void)
{
printk("module b :global_var=%dn",global_var);
return 0;
}
static void hello_exit(void)
{
printk("hello_exit n");
return;
}EXPORT_SYMBOL(global_var);
EXPORT_SYMBOL(show);
MODULE_AUTHOR("yikoulinux");
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);
B模块
#include
#include
extern int global_var;
extern void show(void);
static int hello_init(void)
{
printk("module a: global_var= %dn",global_var);
show();
return 0;
}
static void hello_exit(void)
{
printk("hello_exit n");
return;
}
MODULE_AUTHOR("yikoulinux");
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);
调试步骤: