内核模块在用gcc编译时需要使用特定的参数。另外,一些宏同样需要定义。 这是因为在编译成可执行文件和内核模块时, 内核头文件起的作用是不同的。 以往的内核版本需要我们去在Makefile中手动设置这些设定。尽管这些Makefile是按目录分层次 安排的,但是这其中有许多多余的重复并导致代码树大而难以维护。 幸运的是,一种称为kbuild的新方法被引入,现在外部的可加载内核模块的编译的方法已经同内核编译统一起来。想了解更多的编 译非内核代码树中的模块(就像我们将要编写的)请参考帮助文件linux/Documentation/kbuild/modules.txt。
现在让我们看一个编译名字叫做hello-1.c的模块的简单的Makefile文件:
现在你可以通过执行命令 make -C /usr/src/linux-`uname -r` SUBDIRS=$PWD modules 编译模块。 你应该得到同下面类似的屏幕输出:
[root@pcsenonsrv test_module]# make -C /usr/src/linux-`uname -r` SUBDIRS=$PWD modules make: Entering directory `/usr/src/linux-2.6.x CC [M] /root/test_module/hello-1.o Building modules, stage 2. MODPOST CC /root/test_module/hello-1.mod.o LD [M] /root/test_module/hello-1.ko make: Leaving directory `/usr/src/linux-2.6.x
请注意2.6的内核现在引入一种新的内核模块命名规范:内核模块现在使用.ko的文件后缀(代替 以往的.o后缀),这样内核模块就可以同普通的目标文件区别开。更详细的文档请参考 linux/Documentation/kbuild/makefiles.txt。在研究Makefile之前请确认你已经参考了这些文档。
现在是使用insmod ./hello-1.ko命令加载该模块的时候了(忽略任何你看到的关于内核污染的输出 显示,我们将在以后介绍相关内容)。
所有已经被加载的内核模块都罗列在文件/proc/modules中。cat一下这个文件看一下你的模块是否真的 成为内核的一部分了。如果是,祝贺你!你现在已经是内核模块的作者了。当你的新鲜劲过去后,使用命令 rmmod hello-1.卸载模块。再看一下/var/log/messages文件的内容是否有相关的日志内容。
这儿是另一个练习。看到了在声明
init_module()
上的注释吗? 改变返回值非零,重新编译再加载,发生了什么?