目录
测试模块代码文件结构
里面包含了三个c文件,这个模块编译需要这三个文件对应的.o文件,
Makefile书写
Makefile特殊的地方
1、指定内核模块的编译文件和头文件路径
2、指定编译模块的名称
2、给出当前模块的编译路径
Makefile的书写中所用的到的选项
以下是书写需要的选项,其中红色是必须:
TARGET: 编译生成的目标名称
obj-m:指定编译模块的名称,在编译的时候,会自动找到${TARGET}.c 的文件,将其编译为${TARGET}.o,最终生成${TARGET}.ko。
${TARGET}-objs:当模块来自多个文件时,要用这个来指定需要哪些文件构成,这里的例子需要
hashTable.o netlinkBlack.o netfilter_test.o
KDIR:指定了内核源代码树代码的路径,并用uname -r 构建了此路径,uname命令会提供用户系统的相关信息, -r选项打印出发布内核的信息。
-C:选项要求改变目录到之后的 ${KDIR} 提供的路径中,在那里后发现内核顶层的Makefile。
M=:选项要求在建立内核模块之间,回到指定的路径,一般用pwd命令获得。
KERNELRELEASE:是内核源码的顶层Makefile中定义的一个变量,在第一次读取执行此Makefile时,KERNELRELEASE没有被定义,-C 进入到内核代码,此时KERNELRELEASE被定义。
下面的Makefile提供了两种TARGET的方法:
#Makefile
ifneq ($(KERNELRELEASE),)
#方法一:TARGET=netfilter_test, 代码中有netfilter_test.c的源文件
#TARGET=netfilter_test
#obj-m:= ${TARGET}.o
#${TARGET}-objs:= hashTable.o netlinkBlack.o
#方法二:TARGET=netfilter_module
TARGET:=netfilter_module
obj-m:= ${TARGET}.o
${TARGET}-objs:= hashTable.o netlinkBlack.o netfilter_test.o #这里相较于方法一多一个netfilter_test.o
else
KDIR := /lib/modules/`uname -r`/build
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.ko .tmp_versions *.mod.c *.mod.o .*.cmd *.symvers *.order
endif
编译过程
当执行 make时,目标为default,会执行make -j1 -C $(KDIR) M=$(PWD) modules
编译过程分两次执行Makefile:1、第一次执行此Makefile时 KERNELRELEASE未定义,执行else部分,根据-C选项要求改变目录到之后 $(KDIR)指定的内核源码目录下,读取那里的Makefile,KERNELRELEASE此时被定义;2、根据M=$(PWD) 返回到当前目录继续读入、执行当前的Makefile,这是KERNELRELEASE已在第一步定义了,这是执行if部分,编译obj-m指定的目标。
两种方法的编译日志如下:
运行
以方法二为例,此时编译生成了netfilter_module.ko模块
运行模块:$insmod netfilter_module.ko
查看是否成功: $lsmod | grep netfilter_module
移除模块:$rmmod netfilter_module
凡是过往,即为序章