Skip to content

动态模块加载

一、内核模块介绍

在 Linux 中,.ko 文件是 内核模块(Kernel Object) 的扩展名。内核模块是一种可以 在不重新编译整个内核的情况下动态加载或卸载的代码单元,用于扩展内核功能,例如添加对新硬件设备的驱动支持、文件系统支持或内核特性。模块通过 insmodrmmod 等命令进行加载与卸载, 加载后它就成为内核的一部分,在内核态中运行。

二、编写程序

1. 编写C程序

在源码的驱动目录下新建文件ko_test:

bash
cd linux-5.4/drivers/
mkdir ko_test
cd ko_test
touch ko.c

该文件下输入如下内容,内容和上一节一致,只是为演示动态模块加载:

c
// SPDX-License-Identifier: GPL-2.0
/*
 * My first linux kernel code.
 *
 * Copyright (C) 2025 by DuRuofu
 *
 * This module serves no practical purpose and is solely for testing purposes.
*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>

static int __init fcode_init(void)
{
	pr_info("=============>%s runing<=============\n", __func__);
	return 0;
}

static void __exit fcode_exit(void)
{
	pr_info("=============>%s runing<=============\n", __func__);
}

module_init(fcode_init);
module_exit(fcode_exit);

MODULE_AUTHOR("duruofu");
MODULE_DESCRIPTION("This is my first linux kernel code for testing.");
MODULE_LICENSE("GPL");

2. 编写Makefile

ko_test目录下新建Makefile文件:

CROSS_PREFIX := ~/work/d1s/riscv64-wangzai-linux-gnu-gcc/bin/riscv64-unknown-linux-gnu-
KERNEL_DIR := ~/work/d1s/linux-5.4/
arch := riscv
obj-m := ko.o
cc := $(CROSS_PREFIX)gcc
ld:=$(CROSS_PREFIX)ld
.PHONY:all
all:
	make ARCH=$(arch) CC=$(cc) LD=$(ld) -C $(KERNEL_DIR) M=$(shell pwd) modules V=1
.PHONY:clean
clean:
	make ARCH=$(arch) CC=$(cc) LD=$(ld) -C $(KERNEL_DIR) M=$(shell pwd) clean

这份 Makefile 用于在内核源码外部编译一个内核模块 ko.c。它通过 -C $(KERNEL_DIR) 进入内核源码目录,调用内核自带的模块编译规则, 用交叉编译工具链 (riscv64-unknown-linux-gnu-) 编译出 ko.ko 模块。执行 make 编译即可。

三、编译并配置动态加载

注意需要先编译内核,确保源码目录下生成了内核的可执行文件。

1. 编译

在模块目录下执行:

make

会生成一系列的文件:

这个ko.ko就是可以动态加载的文件了

2. 配置内核支持动态加载

倚旧是这经典的几步:

cd linux-5.4
export ARCH=riscv
export CROSS_COMPILE=/home/duruofu/work/d1s/riscv64-wangzai-linux-gnu-gcc/bin/riscv64-unknown-linux-gnu-
make wangzai_d1s_rtl8723ds_defconfig
make menuconfig

勾选支持模块动态加载:

内核里面的模块也是可以在menuconfig里配置为模块编译的,这点需要注意。

编译内核,并重新制作启动卡烧录即可。

四、测试模块动态加载

1.拷贝编译好的动态模块到开发板

这里在windows上使用adb :

在目录下执行:.\adb.exe shell

通过ADB上传我们编译好的动态模块,使用push命令(注意退出shell):

.\adb.exe push \\wsl.localhost\Ubuntu-20.04-Build-Linux\home\duruofu\work\d1s\linux-5.4\drivers\ko_test\ko.ko /

这里的文件目录根据自己的实际情况填写:

成功后,使用串口终端进行测试:

执行命令insmod ko.ko,加载模块:

可以看到模块被加载了

执行命令rmmod ko.ko,卸载模块: