00. 目录
01. 概述
对于linux内核,可以通过两种方式将内核模块添加到内核中:
- 1、将内核模块编译成内核模块文件,在内核启动后由用户手动动态加载,
- 2、将模块直接编译到内核中去,内核启动时自动加载。
02. 测试代码
test.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
static int __init hello_init(void)
{
printk(KERN_EMERG "Hello Module Init\n");
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_EMERG "Hello Module Exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("uplooking");
MODULE_DESCRIPTION("hello module");
MODULE_ALIAS("test_module");
03. 内核模块编译
内核驱动模块对象所需的构建步骤和编译很复杂,它利用了linux内核构建系统的强大功能, 当然我们不需要深入了解这部分知识,利用简单的Make工具就能编译出我们想要的内核驱动模块。
Makefile参考如下
KERNEL_DIR=/home/deng/code/x3399/kernel
CROSS_COMPILE=aarch64-linux-gnu-gcc
obj-m := test.o
all:
$(MAKE) -C $(KERNEL_DIR) M=`pwd` modules
.PHONE:clean
clean:
$(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
- 第1行: 指定编译内核存放位置
- 第2行: 指定交叉编译工具链
- 第3行: 表示以模块编译
- 第4行: all只是个标号,可以自己定义,是make的默认执行目标。
- 第5行: $(MAKE):MAKE是Makefile中的宏变量,要引用宏变量要使用符号。这里实际上就是指向make程序,所以这里也可以把$(MAKE)换成make.-C:是make命令的一个选项,-C作用是changedirectory. -C dir 就是转到dir目录。M=
pwd
:返回当前目录。这句话的意思是:当make执行默认的目标all时,-C(KERNEL_DIR)指明跳转到内核源码目录下去执行那里的Makefile,-C $(KERNEL_DIR)指明跳转到内核源码目录下去执行那里的Makefile,M=pwd
表示又返回到当前目录来执行当前的Makefile. - 第6行: clean 就是删除后面这些由make生成的文件。
查看当前文件夹,新增test.ko,这就是我们自己编写、编译的内核驱动模块。
deng@local:~/code/test/1module$ make
make -C /home/deng/code/x3399/kernel M=`pwd` modules
make[1]: 进入目录“/home/deng/code/x3399/kernel”
CC [M] /home/deng/code/test/1module/test.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/deng/code/test/1module/test.mod.o
LD [M] /home/deng/code/test/1module/test.ko
make[1]: 离开目录“/home/deng/code/x3399/kernel”
deng@local:~/code/test/1module$
deng@local:~/code/test/1module$ ls
Makefile Module.symvers test.ko test.mod.o
modules.order test.c test.mod.c test.o
deng@local:~/code/test/1module$
04. 内核模块加载和卸载
编译好内核驱动模块,可以通过多种方式将test.ko拷贝到开发板,一般主要使用NFS网络文件系统或者SCP命令。
加载模块
[root@rk3399:/mnt/code/test/1module]# ls
Makefile modules.order test.ko test.mod.o
Module.symvers test.c test.mod.c test.o
[root@rk3399:/mnt/code/test/1module]# insmod test.ko
[ 652.669514] Hello Module Init
[root@rk3399:/mnt/code/test/1module]#
卸载模块
[root@rk3399:/mnt/code/test/1module]# rmmod test
[ 668.206247] Hello Module Exit
[root@rk3399:/mnt/code/test/1module]#