模块参数
module_param(name,type, perm);
module_param_array(name, type, num, perm);
perm表示该参数在sysfs文件系统中所对应的文件节点的属性;你应该使用<linux/stat.h>中定义的权限值;这个值决定谁可以存取这些模块参数在sysfs文件系统中的表示;当perm为0时,表示此参数不存在sysfs文件系统下对应的文件节点;否则,模块被加载后,在/sys/module/目录下将会出现以此模块名命名的目录,带有给定的权限;在该目录下,有一个parameters子目录,在里面每个文件对应一个参数,参数值就在以该参数名命名的文件中。
注意:如果一个参数被sysfs修改了,那么你的模块看到的参数值也被修改了,但是你的模块不会收到任何通知;你应当不要使模块参数可写,除非你准备好检测这个改变并因而作出反应。
模块符号
EXPORT_SYMBOL标签内定义的函数对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用。
加入B中调用A中导出函数
[1] 在模块A中c文件或者头文件中使用EXPORT_SYMBOL(xxxx)导出函数.有些需要添加编译选项-DEXPORT_SYMTAB.
[2] 在模块B中用"extern" 申明函数(如, extern int xxxx);申明以后就能够直接使用导出的函数了。
另外:在导出函数以后,可以使用 cat proc/kallsyms来查看所有的导出符号,其中属性为t的标识是不能被调用的,所以如果导出符号是t类型,那么无法直接被其他模块使用。
无法导出问题解决
方法一:在A模块编译好后会生成符号表文件Module_symvers,里面有函数地址和函数名对应关系,把这个文件拷贝到需要调用的B的源代码下,替换B的该文件。
然后重新编译B模块.这样就能够让B调用A的函数,以后加载模块顺序也必须先A后B,卸载相反。
方法二:将两个模块放在一个目录下,进行编译。其实和方法一类似。
这样就能够成功的实现两个模块之间的函数调用,比如KVM如果需要和驱动模块相互调用,就能使用这个方法。如果是两个模块之间需要相互调用,可以让驱动模块函数导出,KVM模块将函数指针当做回调函数传给驱动,是想双方的函数调用通讯。
方法一:在A模块编译好后会生成符号表文件Module_symvers,里面有函数地址和函数名对应关系,把这个文件拷贝到需要调用的B的源代码下,替换B的该文件。
然后重新编译B模块.这样就能够让B调用A的函数,以后加载模块顺序也必须先A后B,卸载相反。
方法二:将两个模块放在一个目录下,进行编译。其实和方法一类似。
这样就能够成功的实现两个模块之间的函数调用,比如KVM如果需要和驱动模块相互调用,就能使用这个方法。如果是两个模块之间需要相互调用,可以让驱动模块函数导出,KVM模块将函数指针当做回调函数传给驱动,是想双方的函数调用通讯。
/*
* 内核符号导出 给其他模块使用 使用前要申明一下
* 另外从 /proc/kallsyms 可以查看内核符号表的相关信息(eg.所在内存地址)
* eg. cat /proc/kallsyms | grep integar
*/
* 内核符号导出 给其他模块使用 使用前要申明一下
* 另外从 /proc/kallsyms 可以查看内核符号表的相关信息(eg.所在内存地址)
* eg. cat /proc/kallsyms | grep integar
*/
#include<linux/init.h>
#include<linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int __init symbol_init(void)
{
printk("<0> symbol_init\n");
return 0;
}
int add_integar(int a, int b)
{
return (a + b);
}
int sub_integar(int a, int b)
{
return (a - b);
}
static void __exit symbol_exit(void)
{
printk("<0> symbol_exit\n");
}
EXPORT_SYMBOL(add_integar);
EXPORT_SYMBOL(sub_integar);
module_init(symbol_init);
module_exit(symbol_exit);
/*
*使用其他内核模块导出的符号
*/
*使用其他内核模块导出的符号
*/
#include<linux/module.h>
#include<linux/init.h>
extern int add_integar(int, int);
extern int sub_integar(int, int);
MODULE_LICENSE("GPL");
static int __init use_symbol_init(void)
{
printk("<0> use_symbol_init");
printk("<0> 1+2 = %d\n",add_integar(1,2));
printk("<0> 3-2 = %d\n",sub_integar(3,2));
return 0;
}
static void __exit use_symbol_exit(void)
{
printk("<0> Module exit!\n");
}
module_init(use_symbol_init);
module_exit(use_symbol_exit);