linux内核模块编译
1 Makefile编写
ifneq ($(KERNELRELEASE),)
obj-m := mytest.o
mytest-objs := file1.o file2.o file3.o
else
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) M=$(PWD) modules//到linux源码所在的目录执行主Makefile 并当前路径传给主Makefile,告诉主Makefile执行完后返回到当前目录,执行Makefile
endif
解释为:
KERNELRELEASE
是在内核源码的顶层Makefile中定义的一个变量,在第一次读取执行此Makefile时,KERNELRELEASE没有被定义,
所以make将读取执行else之后的内容。如果make的目标是clean,直接执行clean操作,然后结束。当make的目标为all时,-C
$(KDIR) 指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD)
表明然后返回到当前目录继续读入、执行当前的Makefile。当从内核源码目录返回时,KERNELRELEASE已被被定义,kbuild也被启动去
解析kbuild语法的语句,make将继续读取else之前的内容。else之前的内容为kbuild语法的语句,
指明模块源码中各文件的依赖关系,以及要生成的目标模块名。mytest-objs := file1.o file2.o
file3.o表示mytest.o 由file1.o,file2.o与file3.o 连接生成。obj-m :=
mytest.o表示编译连接后将生成mytest.o模块。
2 测试
源文件
1 // 2 //hello.c 3 // 4 #include <linux/init.h> 5 #include <linux/kernel.h> 6 #include <linux/module.h> 7 8 static int hello_init(void) { 9 printk(KERN_WARNING "Module init: Hello world!\n"); 10 return 0; 11 } 12 13 static void hello_exit(void) { 14 printk(KERN_WARNING "Module exit: bye-bye\n"); 15 } 16 17 module_init(hello_init); 18 module_exit(hello_exit);
Makefile文件
1 ifneq ($(KERNELRELEASE),) 2 obj-m:=hello.o 3 else 4 KDIR := /lib/modules/$(shell uname -r)/build 5 6 all: 7 make -C $(KDIR) M=$(PWD) modules 8 clean: 9 make -C $(KDIR) M=$(PWD) clean 10 endif
插入模块到内核
# insmod hello.ko
查看输出
[root@localhost demo]# dmesg | tail -n 5
<span>[ 2445.017321] virbr0: port 2(vif1.0) entering forwarding state
[ 2445.017439] virbr0: port 2(vif1.0) entering disabled state
[ 2494.639683] hello: module license 'unspecified' taints kernel.
[ 2494.639688] Disabling lock debugging due to kernel taint
[ 2494.639841] Module init: Hello world!