1内核污染问题
当新加载的模块未声明许可证或者许可证不被内核认可的时候,内核将输出kernel tainted警告。这种情况,一般被称为内核污染。
声明许可证的方法:
MODULE_LICENSE(“licensename”)
声明许可证的举例
MODULE_LICENSE("DualBSD/GPL");
MODULE_LICENSE("GPL");
MODULE_LICENSE("BSD ");
内核认可(即不会认为受到污染)的证书类型如下:
GPL
BSD
DualBSD/GPL
内核污染标志本身上不会对内核的使用产生任何影响。
2符号导出问题
导出方法有以下两种
EXPORT_SYMBOL
EXPORT_SYMBOL_GPL
导出的“符号”可以是变量,也可以是函数。
导出和”static”概念有区别:
1:static在内核中的含义也只是限定一个变量只有本文件可以使用。
2:Static限制的变量也可以导出。
3:所有导出了的变量名都是唯一的。
4:只要导出了的变量就可以在其他模块使用,无论次变量是否static修饰。
5:一个变量或函数能不能由本模块中的其他文件使用,是由static修饰决定,规则与普通C语言规则一样,无论此函数是否导出。
总结地说,static的限制范围作用于模块本身以及模块自己的编译过程。导出的作用范围是模块加载入内核后的内核符号表。
3模块版本问题
CONFIG_MODVERSIONS内核选项打开后,加载模块时,内核将会强制验证模块的版本,如果和内核版本不一致,内核会拒绝加载。
模块的内核版本记录在于模块一起编译的.mod.c文件中,一般形式如下:
MODULE_INFO(vermagic,VERMAGIC_STRING);
v2.6.34.8的menuconfig中只有version检查的选项,
但是(不知道是内核升级还是发布版定制导致),后续还出现了校验内核接口CRC的版本校验,导致即使同一个小版本号的内核,只要源码树不同,编译出的模块就可能无法互通。
解决办法:
1:模块与内核在同一个目录树下编译
2:解除内核的版本检查机制。
4符号寻址问题
内核所有函数的名字与地址的对应关系都是被内核保存了的。从/proc/kallsyms可以看到这个对应关系。新加入的模块,想调用内核中已经导出的函数,就需要查这张表。同样,内核中已有的模块,想调用新加入的模块的函数,也需要查找这张表。幸运的是,这个复杂的查找过程对于我们来说是完全透明的。
从/proc/kallsyms文件中也可以看见你刚加载的模块的函数,以及他们在内核空间中的地址。
5编译时自动补齐的部分
编译模块时产生的.mod.c文件记录了这个模块的很多信息,比如版本。这个.c文件将与你自己写的.c模块一起编译成模块。
6自动drop的代码段
当一个函数被标注为__init的时候,它将被加载并使用一次,然后保存其代码的内存将被释放。这是一个半自动的过程:编程者指定哪些代码只用一次,而内核按照编程者的指定丢弃使用过的代码。
一般模块加载时的入口函数会被标记为__init。这个函数与模块中其他函数的不同就在于:其他函数将被加载进内核的代码空间中,直到卸载模块为止;而这个“初始化函数”,开始时也会被加载进内核的代码空间中,但是内核在调用过一次后,就会将这段代码自动自动丢弃掉,内核的代码空间中再也看不见这个函数了。