当前位置:我的异常网» Linux/Unix » 『分享』从 2.4 到 2.6:Linux 内核可装载模块机制
『分享』从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响! (转载),该如何解决(3)
www.myexceptions.net 网友分享于:2013-01-07 浏览:7次
回页首
2.5 模块输出的内核符号
2.4 内核下,缺省情况时模块中的非静态全局变量及函数在模块加载后会输出到内核空间。
2.6 内核下,缺省情况时模块中的非静态全局变量及函数在模块加载后不会输出到内核空间,需要显式调用宏EXPORT_SYMBOL才能输出。所以在2.6 内核的模块下,EXPORT_NO_SYMBOLS宏的调用没有意义,是空操作。在同时支持2.4与2.6内核的设备驱动中,可以通过以下代码段来输出模块的内核符号
清单6: 同时支持2.4与2.6的输出内核符号代码段
#include
#ifndef LINUX26
EXPORT_NO_SYMBOLS;
#endif
EXPORT_SYMBOL(var);
EXPORT_SYMBOL(func);
需要注意的是如需在2.4内核下使用 EXPORT_SYMBOL,必须在 CFLAGS中定义 EXPORT_SYMTAB,否则编译将会失败。
从良好的代码风格角度出发,模块中不需要输出到内核空间且不需为模块中其它文件所用的全局变量及函数最好显式申明为static类型,需要输出的内核符号以模块名为前缀。
模块加载后,2.4内核下可通过 /proc/ksyms、 2.6 内核下可通过/proc/kallsyms查看模块输出的内核符号
回页首
2.6 模块的命令行输入参数
在装载内核模块时,用户可以向模块传递一些参数,如`modprobe modname var=value`,否则,var将使用模块内定义的缺省值。
2.4内核下,linux/module.h中定义有宏MODULE_PARM(var,type) 用于向模块传递命令行参数。var为接受参数值的变量名,type为采取如下格式的字符串[min[-max]]{b,h,i,l,s}。min及max用于表示当参数为数组类型时,允许输入的数组元素的个数范围;b:byte;h:short;i:int;l:long;s:string。
2.6内核下,宏MODULE_PARM(var,type)不再被支持。在头文件linux/moduleparam.h里定义了如下宏:
module_param(name, type, perm)
module_param_array(name, type, nump, perm)
type 类型可以是byte、short,、ushort、 int、 uint、long、ulong、charp, bool or invbool, 不再采用2.4内核中的字符串形式,而且在模块编译时会将此处申明的type与变量定义的类型进行比较,判断是否一致。
perm表示此参数在sysfs文件系统中所对应的文件节点的属性。2.6内核使用sysfs文件系统,这是一个建立在内存中比proc更强大的文件系统。sysfs文件系统可以动态、实时,有组织层次地反应当前系统中的硬件、驱动等状态。当perm为0时,表示此参数不存在sysfs文件系统下对应的文件节点。模块被加载后,在/sys/module/ 目录下将出现以此模块名命名的目录。如果此模块存在perm不为0的命令行参数,在此模块的目录下将出现parameters目录,包含一系列以参数名命名的文件节点,这些文件的权限值等于perm,文件的内容为参数的值。
nump 为保存输入的数组元素个数的变量的指针。当不需保存实际输入的数组元素个数时,可以设为NULL。从2.6.0至2.6.10 版本,须将变量名赋给nump;从2.6.10 版本开始,须将变量的引用赋给nump,这更易为开发人员理解。加载模块时,使用逗号分隔输入的数组元素。
清单7: 适用于2.4与2.6内核的模块输入参数模板
#include
#ifdef LINUX26
#include
#endif
int debug = 0;
char *mode = "800x600";
int tuner[4] = {1, 1, 1, 1};
#ifdef LINUX26
int tuner_c = 1;
#endif
#ifdef LINUX26
MODULE_PARM(debug, "i");
MODULE_PARM(mode, "s");
MODULE_PARM(tuner,"1-4i");
#else
module_param(debug, int, 0644);
module_param(mode, charp, 0644);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
module_param_array(tuner, int, &tuner_c, 0644);
#else
module_param_array(tuner, int, tuner_c, 0644);
#endif
#endif
模块编译生成后,加载模块时可以输入:`modprobe my_module mode=1024x768 debug=1 tuner=22,33`。
在linux/moduleparam.h还定义有:
module_param_array_named(name, array, type, nump, perm)
module_param_call(name, set, get, arg, perm)
module_param_named(name, value, type, perm)
读者可以参阅linux/moduleparam.h查看这些宏的详细描述,有一点需注意,在2.6内核里,module_param这一系列宏使用的都是小写名字。
2.7 模块的许可证声明
从2.4.10版本内核开始,模块必须通过MODULE_LICENSE宏声明此模块的许可证,否则在加载此模块时,会收到内核被污染"kernel tainted" 的警告。从linux/module.h文件中可以看到,被内核接受的有意义的许可证有 "GPL","GPL v2","GPL and additional rights","Dual BSD/GPL","Dual MPL/GPL","Proprietary"。
在同时支持2.4与2.6内核的设备驱动中,模块可按如下方式声明自己的许可证。
清单8: 适用于2.4与2.6内核的模块许可证声明模板
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10)
MODULE_LICENSE("GPL");
文章评论