的确,在下载了Linux的源代码之后,Linux的Makefile提供个很完善灵活的编译方法,比如:make menuconfig 可以让我们非常方便的编译一个完整的内核。
但是,对于模块开发来说我们不需要编译一个完整的内核,而只更改对应模块中的部分代码。那么本文就一步一步的告诉你该怎么编译一个驱动模块,比如NVMe驱动(默认你已经下载了完整的Linux源代码)。
- 确定将要运行你新编译的模块的平台的Linux版本信息
uname -r
笔者的平台信息是:5.13.0-41-generic
如果你不确认主机平台的信息,而随意使用其它版本的Linux源码编译的话,那你在插入模块的时候会遇到以下错误:
insmod: ERROR: could not insert module nvme.ko: Invalid module format
- 根据运行平台的版本信息,将Linux源代码的版本切换到相应的版本
git reset --hard v5.13-rc7
- 进入到目标模块目录中,更改Makefile
cd drivers/nvme
# 在Makefile的最后添加以下命令
# 如果你是在运行平台上编译的,你可以直接用下面这一行,来动态的找到平台的Linux版本编译模块所需的目录
# KERNEL_DIR = /lib/modules/`uname -r`/build
KERNEL_DIR = /lib/modules/5.13.0-40-generic/build
MODULEDIR := $(shell pwd)
modules:
make -C $(KERNEL_DIR) M=$(MODULEDIR) modules
- 更改驱动模块源代码
# 在模块进入函数:nvme_init 中随便加入一句打印
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index a29b170701fc..a09ea1e5aa7e 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -3317,6 +3317,7 @@ static int __init nvme_init(void)
BUILD_BUG_ON(sizeof(struct nvme_create_sq) != 64);
BUILD_BUG_ON(sizeof(struct nvme_delete_queue) != 64);
BUILD_BUG_ON(IRQ_AFFINITY_MAX_SETS < 2);
+ printk("This is new test driver");
return pci_register_driver(&nvme_driver);
}
- 编译,等待完成
make
- 安装
insmod host/nvme-core.ko insmod host/nvme.ko
如果你在插入模块的时候遇到了这个问题:
ERROR: could not insert module host/nvme.ko: Unknown symbol in module
说明是依赖模块没有插入,你可以使用以下命令来获取依赖模块的名称,然后先把对应模块插入。
modinfo xxx.ko | grep depends
- 查看
dmesg



