字符设备驱动的Makefile,驱动的插入和卸载 1 字符设备驱动的Makefile 1 2 3 4 5 6 7 8 9 10 ifneq ($(KERNELRELEASE) ,) obj-m := hello_dev.o else PWD := $(shell pwd) KDIR := /lib/modules/`uname -r`/build all: make -C $(KDIR) M=$(PWD) clean: rm -rf *.o *.ko *.mod.c *.symvers *.c~ *~ endif
首先判断 KERNELRELEASE 变量是否为空,刚开始这个变量肯定没有被定义,于是控制流跳转到else 分支
在 else 分支中,定义变量 PWD 表示当前所在目录,定义变量 KDIR 表示内核所在目录,make -C $(KDIR) M=$(PWD)这一行的规则是:先进入 -C 指定的内核所在目录执行Makefile文件,在这个Makefile文件中会设置变量 KERNELRELEASE;“M=”选项的作用是,当用户需要以某个内核为基础编译1个外部模块,程序会自动到 “M=” 指定的 dir 目录中查找模块源码,将其编译,生成 .ko 文件
这里的 M 是内核根目录下 Makefile 中使用的变量,
1 2 3 4 5 6 7 8 9 10 ifdef SUBDIRS KBUILD_EXTMOD ?= $(SUBDIRS) endif ifeq ("$(origin M)" , "command line" ) KBUILD_EXTMOD := $(M) endif
obj-m 指定目标文件,表示将由 c 代码编译成 .o 文件,然后生成独立的 .ko 模块,不会编译到 zImage
在驱动源码目录下执行 make 命令,
1 2 3 4 5 6 7 8 9 10 $ make make -C /lib/modules/`uname -r`/build M=/home/lnhoo/workspace/c/src/hello_dev make[1]: Entering directory `/usr/src/linux-headers-4.4.0-142-generic' LD /home/lnhoo/workspace/c/src/hello_dev/built-in.o CC [M] /home/lnhoo/workspace/c/src/hello_dev/hello_dev.o Building modules, stage 2. MODPOST 1 modules CC /home/lnhoo/workspace/c/src/hello_dev/hello_dev.mod.o LD [M] /home/lnhoo/workspace/c/src/hello_dev/hello_dev.ko make[1]: Leaving directory `/usr/src/linux-headers-4.4.0-142-generic'
2 驱动的插入和卸载 2.1 插入
1 $ sudo insmod hello_dev.ko
此时查看内核模块列表,
1 2 3 4 5 6 7 $ lsmod Module Size Used by hello_dev 16384 0 crct10dif_pclmul 16384 0 crc32_pclmul 16384 0 ghash_clmulni_intel 16384 0 ......
hello_dev 驱动出现在列表中
此时加载驱动模块,然后查看内核日志,
1 2 3 4 5 $ dmesg [ 331.039816] hello_dev: loading out-of-tree module taints kernel. [ 331.039869] hello_dev: module verification failed: signature and/or required key missing - tainting kernel [ 331.040488] register_chrdev_region ok [ 331.040490] hello driver init
hello_dev 字符设备驱动程序入口函数中的 printk 成功将消息写入内核日志
2.2 卸载
执行 lsmod 命令查看内核模块列表,此时 hello_dev 驱动已不在列表中