首先引用一篇文章 http://blog.csdn.net/zqixiao_09/article/details/50838043linux
1.我先写好一个驱动hello.cshell
#include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); /* 加载模块时调用的函数 */ static int hello_init(void) { printk(KERN_ALERT "world\n");//KERN_ALERT 0 报告消息,表示必须当即采起措施 return 0; } /* 卸载模块时调用的函数 */ static void hello_exit(void) { printk(KERN_ALERT "goodbye\n"); } /* 注册模块入口和出口 */ module_init(hello_init); module_exit(hello_exit); MODULE_AUTHOR("ZQH"); MODULE_DESCRIPTION("a simple module"); MODULE_ALIAS("first module");
2.编写Makefile函数
ifneq ($(KERNELRELEASE),) obj-m:=hello.o else KDIR := /lib/modules/$(shell uname -r)/build PWD:=$(shell pwd) all: make -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.symvers *.cmd *.cmd.o endif
(1)KERNELRELEASE 在linux内核源代码中的顶层makefile中有定义ui
(2)shell pwd 取得当前工做路径spa
(3)shell uname -r 取得当前内核的版本号.net
(4)KDIR 当前内核的源代码目录。code
make 的的执行步骤blog
a -- 第一次进来的时候,宏“KERNELRELEASE”未定义,所以进入 else;ci
b -- 记录内核路径,记录当前路径;开发
因为make 后面没有目标,因此make会在Makefile中的第一个不是以.开头的目标做为默认的目标执行。默认执行all这个规则
c -- make -C $(KDIR) M=$(PWD) modules
-C 进入到内核的目录执行Makefile ,在执行的时候KERNELRELEASE就会被赋值,M=$(PWD)表示返回当前目录,再次执行makefile,modules 编译成模块的意思
因此这里实际运行的是
make -C /lib/modules/2.6.13-study/build M=/home/fs/code/1/module/hello/ modules
d -- 再次执行该makefile,KERNELRELEASE就有值了,就会执行obj-m:=hello.o
obj-m:表示把hello.o 和其余的目标文件连接成hello.ko模块文件,编译的时候还要先把hello.c编译成hello.o文件
能够看出make在这里一共调用了3次
3.编译
zqh@linux:~/Desktop/hello$ make make -C /lib/modules/4.13.0-36-generic/build M=/home/zqh/Desktop/hello modules make[1]: Entering directory '/usr/src/linux-headers-4.13.0-36-generic' CC [M] /home/zqh/Desktop/hello/hello.o /home/zqh/Desktop/hello/hello.c:4:12: warning: ‘hello_init’ defined but not used [-Wunused-function] static int hello_init(void) ^ /home/zqh/Desktop/hello/hello.c:10:13: warning: ‘hello_exit’ defined but not used [-Wunused-function] static void hello_exit(void) ^ Building modules, stage 2. MODPOST 1 modules CC /home/zqh/Desktop/hello/hello.mod.o LD [M] /home/zqh/Desktop/hello/hello.ko make[1]: Leaving directory '/usr/src/linux-headers-4.13.0-36-generic'
4.加载模块 卸载模块
zqh@linux:~/Desktop/hello$ su root@linux:/home/zqh/Desktop/hello# insmod hello.ko root@linux:/home/zqh/Desktop/hello# rmmod hello root@linux:/home/zqh/Desktop/hello# dmesg | tail [ 396.867685] pcieport 0000:00:1c.0: BAR 15: assigned [mem 0xf2400000-0xf25fffff 64bit pref] [ 396.867702] pcieport 0000:00:1c.1: BAR 15: assigned [mem 0xf2600000-0xf27fffff 64bit pref] [ 396.867708] pcieport 0000:00:1c.0: BAR 13: assigned [io 0x2000-0x2fff] [ 396.867713] pcieport 0000:00:1c.1: BAR 13: assigned [io 0x3000-0x3fff] [ 2964.543768] hello: loading out-of-tree module taints kernel. [ 2964.543814] hello: module verification failed: signature and/or required key missing - tainting kernel [ 3980.513820] world [ 4000.782155] goodbye
5.交叉编译到嵌入式开发板
#General Purpose Makefile for cross compile Linux Kernel module ifneq ($(KERNELRELEASE),) obj-m := hello.o #+=是链接字符串 else ARCH := arm CROSS_COMPILE := arm-linux-gnueabihf- KERN_DIR := /home/zqh/lichee/linux-zero-4.14.y #选择内核路径 PWD :=$(shell pwd) #当前路径 all: make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERN_DIR) M=$(PWD) modules clean: make -C $(KERN_DIR) M=$(shell pwd) modules clean rm -rf modules.order endif
相似这个makefile的配置便可