编译内核模块

内核模块在用gcc编译时需要使用特定的参数。另外,一些宏同样需要定义。 这是因为在编译成可执行文件和内核模块时, 内核头文件起的作用是不同的。 以往的内核版本需要我们去在Makefile中手动设置这些设定。尽管这些Makefile是按目录分层次 安排的,但是这其中有许多多余的重复并导致代码树大而难以维护。 幸运的是,一种称为kbuild的新方法被引入,现在外部的可加载内核模块的编译的方法已经同内核编译统一起来。想了解更多的编 译非内核代码树中的模块(就像我们将要编写的)请参考帮助文件linux/Documentation/kbuild/modules.txt

现在让我们看一个编译名字叫做hello-1.c的模块的简单的Makefile文件:

Example 2-2. 一个基本的Makefile

obj-m += hello-1.o

现在你可以通过执行命令 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()上的注释吗? 改变返回值非零,重新编译再加载,发生了什么?