1. 内核模块的Makefile
若要编译hello的内核模块,最简单的方法就是要编写如下内容的Makefile(若对Makefile比较陌生,请参考Linux开发基础讲义):
-----------------------------------------------------------------------
ifeq ($(KERNELRELEASE),)
KERNELDIR ?=/usr/src/kernels/2.6.18-8.el5xen-i686 #指向你的内核代码目录
#KERNELDIR ?=/home/eetek/linux-2.6.29-eetek
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules #编译内核模块的指令
clean: #删除生成的所有文件
rm -rf modules.* *.o *~ core .depend .*.cmd *.ko
rm –rf *.mod.c .tmp_versions Module*
.PHONY: modules modules_install clean
else
obj-m := hello.o #你要编译的模块名称
endif
-----------------------------------------------------------------------
对于上述的Makefile需要特别说明如下几点:
(1) $(MAKE) -C $(KERNELDIR) M=$(PWD) modules #编译内核模块的指令
ü 理解这条指令,首先需要理解make命令选项-C的作用,-C是指Change Directory。
ü MAKE是Makefile中的宏变量,和KERNELDIR相似,要引用这个宏变量的值需要使用$符号。在这里实际上就是指向make程序。注:此时应该写为$(MAKE),而不能写成$MAKE,请思考为什么。
ü M=$(PWD) 是指要编译的内核模块的源程序在那个目录下,$(PWD)指与Makefile在同一目录下,也就是当前目录。(pwd命令的作用是:print work directory).modules指明要按照内核模块的方式编译。
结合起来理解,就是进入$(KERNELDIR)的目录,并且执行make命令,如果没有M=$(PWD) modules,make –C $(KERNELDIR)将是编译Linux内核映像的指令。M=$(PWD) modules也就是按照$(KERNELDIR)中内核模块的方式编译$(PWD)目录下的程序。modules实际上是$(KERNELDIR)目录下的Makefile的一个Target入口.
既然是为$(KERNELDIR)编译内核模块,所以必须要求$(KERNELDIR)这个内核必须正确配置,并且得到编译的,以为编译模块的过程需要使用内核配置的相关信息,比如处理器的类型等。至于如何配置Linux内核,请参考Linux系统移植过程中的相关实验。
(2) obj-m = hello.o #你要编译的模块名称
这里必须和$(PWD)目录下C程序文件的名称相对应,如果C程序文件为world.c,那么必须修改成obj-m = world.o.
和很多C语言程序一样,一个内核模块也可能有多个C程序文件,那么如何修改Makefile让其编译成一个内核模块呢?此时,需要将obj-m = hello.o换成如下代码:
Obj-m = hello.o
Hello-objs = hello1.o, hello2.o
(3) clean是Makefile的入口,其目的是为了清除所有生成的文件。
正确的配置和编译了$(KERNELDIR)的内核,就可以编译hello的内核模块了,你将会在当前的目录中看到一个hello.ko的内核模块,下面我们看看如何想内核中动态的加载和删除。