内核模块在用gcc编译时需要使用特定的参数。另外,一些宏同样需要定义。 这是因为在编译成可执行文件和内核模块时, 内核头文件起的作用是不同的。 以往的内核版本需要我们去在Makefile中手动设置这些设定。尽管这些Makefile是按目录分层次 安排的,但是这其中有许多多余的重复并导致代码树大而难以维护。 幸运的是,一种称为kbuild的新方法被引入,现在外部的可加载内核模块的编译的方法已经同内核编译统一起来。想了解更多的编 译非内核代码树中的模块(就像我们将要编写的)请参考帮助文件linux/Documentation/kbuild/modules.txt。
现在让我们看一个编译名为hello-1.c的模块的简单的Makefile:
Example 2-2. 一个基本内核模块的Makefile
obj-m += hello-1.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean |
现在你可以通过执行命令 make编译模块。 你应该得到同下面类似的屏幕输出:
hostname:~/lkmpg-examples/02-HelloWorld# make make -C /lib/modules/2.6.11/build M=/root/lkmpg-examples/02-HelloWorld modules make[1]: Entering directory `/usr/src/linux-2.6.11' CC [M] /root/lkmpg-examples/02-HelloWorld/hello-1.o Building modules, stage 2. MODPOST CC /root/lkmpg-examples/02-HelloWorld/hello-1.mod.o LD [M] /root/lkmpg-examples/02-HelloWorld/hello-1.ko make[1]: Leaving directory `/usr/src/linux-2.6.11' hostname:~/lkmpg-examples/02-HelloWorld# |
请注意2.6的内核现在引入一种新的内核模块命名规范:内核模块现在使用.ko的文件后缀(代替 以往的.o后缀),这样内核模块就可以同常规的目标文件区别开。这样做的理由是它们包含一个附加的.modinfo段, 那里存放着关于模块的附加信息。我们将马上看到这些信息的好处。
使用modinfo hello-*.ko来看看它是什么样的信息。
hostname:~/lkmpg-examples/02-HelloWorld# modinfo hello-1.ko filename: hello-1.ko vermagic: 2.6.11 preempt PENTIUMII 4KSTACKS gcc-3.3 depends: |
到目前为止,没什么惊人的。一旦我们对后面的一个例子,hello-5.ko,使用modinfo,那将会改变。
hostname:~/lkmpg-examples/02-HelloWorld# modinfo hello-5.ko filename: hello-5.ko license: GPL author: Peter Jay Salzman vermagic: 2.6.11 preempt PENTIUMII 4KSTACKS gcc-3.3 depends: parm: myintArray:An array of integers (array of int) parm: mystring:A character string (charp) parm: mylong:A long integer (long) parm: myint:An integer (int) parm: myshort:A short integer (short) hostname:~/lkmpg-examples/02-HelloWorld# |
这里有很多有用的信息去看。报告错误的作者信息,许可证信息,甚至对它接受参数的简短描述。
更详细的文档请参考 linux/Documentation/kbuild/makefiles.txt。在研究Makefile之前请确认你已经参考了这些文档。它很可能会节省你很多工作。
现在是使用insmod ./hello-1.ko命令加载该模块的时候了(忽略任何你看到的关于内核污染的输出 显示,我们将在以后介绍相关内容)。
所有已经被加载的内核模块都罗列在文件/proc/modules中。cat一下这个文件看一下你的模块是否真的 成为内核的一部分了。如果是,祝贺你!你现在已经是内核模块的作者了。当你的新鲜劲过去后,使用命令 rmmod hello-1.卸载模块。再看一下/var/log/messages文件的内容是否有相关的日志内容。