linux模块开发必要的基础知识

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。这个函数与模块中其他函数的不同就在于:其他函数将被加载进内核的代码空间中,直到卸载模块为止;而这个“初始化函数”,开始时也会被加载进内核的代码空间中,但是内核在调用过一次后,就会将这段代码自动自动丢弃掉,内核的代码空间中再也看不见这个函数了。

转自:http://bbs.chinaunix.net

看看花儿冲破北疆漫漫寒冬,妖娆绽放;

linux模块开发必要的基础知识

相关文章:

你感兴趣的文章:

标签云: