前言
本文记录了下我在学Linux内核开发这个课程时,第一课时的实验的内容。
实验环境
我是用的阿里云云服务器 Debian13系统 进行实验。
编写内核模块源码
第一个文件:vser.c(总共两个文件,放在相同目录下)
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
int init_module(void)
{
printk("module init\n");
return 0;
}
void cleanup_module(void)
{
printk("cleanup module\n");
}
MODULE_LICENSE("GPL");
第二个文件,Makefile
ifeq ($(KERNELRELEASE),)
ifeq ($(ARCH),arm)
KERNELDIR ?= /home/farsight/fs4412/linux-3.14.25-fs4412
ROOTFS ?= /nfs/rootfs
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
endif
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) INSTALL_MOD_PATH=$(ROOTFS) modules_install
clean:
rm -rf *.o *.ko .*.cmd *.mod.* modules.order Module.symvers .tmp_versions
else
obj-m := vser.o
endif
编译内核模块
在刚刚放文件的目录下,输入make进行编译。
No such file or directory报错
使用make编译的时候,报如下的错误
cmake.txt Makefile vser.c
root\@iZn4a73i0mqohljrenhyi4Z:\~/work\_1# make
make -C /lib/modules/6.12.57+deb13-amd64/build M=/root/work\_1 modules
make\[1]: Entering directory '/root/work\_1'
make\[1]: \*\*\* /lib/modules/6.12.57+deb13-amd64/build: No such file or directory. Stop.
make\[1]: Leaving directory '/root/work\_1'
make: \*\*\* \[Makefile:12: modules] Error 2
root\@iZn4a73i0mqohljrenhyi4Z:\~/work\_1# make
make -C /lib/modules/6.12.57+deb13-amd64/build M=/root/work\_1 modules
make\[1]: Entering directory '/root/work\_1'
make\[1]: \*\*\* /lib/modules/6.12.57+deb13-amd64/build: No such file or directory. Stop.
make\[1]: Leaving directory '/root/work\_1'
make: \*\*\* \[Makefile:12: modules] Error 2
root\@iZn4a73i0mqohljrenhyi4Z:\~/work\_1# cd /lib/mod
modprobe.d/ modules/\
root\@iZn4a73i0mqohljrenhyi4Z:\~/work\_1# cd /lib/mod
这个主要的报错是
/lib/modules/6.12.57+deb13-amd64/build: No such file or directory
导致这个的原因是 当前系统没有安装对应的内核头文件和内核构建目录。我们需要安装下相关依赖。
apt install -y build-essential
apt install -y linux-headers-$(uname -r)
当然 如果安装出现报错
oot\@iZn4a73i0mqohljrenhyi4Z:\~/work\_1# uname -r
6.12.57+deb13-amd64
root\@iZn4a73i0mqohljrenhyi4Z:\~/work\_1# apt install -y linux-headers-6.12.57+deb13-amd64
Error: Unable to locate package linux-headers-6.12.57+deb13-amd64
Error: Couldn't find any package by glob 'linux-headers-6.12.57+deb13-amd64'
root\@iZn4a73i0mqohljrenhyi4Z:\~/work\_1#
这是因为当前系统的软件源,没有当前运行的内核的构建工具。
解决方案就是更换系统内核(当然也有别的方案)。更换为有构建工具的。更新命令如下
apt install -y build-essential linux-image-amd64 linux-headers-amd64
执行完后重启系统。再次编译,应该可以看到没有这个构建报错了。(如有需要,可以make clean处理下之前的垃圾文件)
missing MODULE_LICENSE() in….报错
报错详情:
rm -rf \*.o *.ko .*.cmd *.mod.* modules.order Module.symvers .tmp\_versions
root\@iZn4a73i0mqohljrenhyi4Z:\~/work\_1# make
make -C /lib/modules/6.12.74+deb13+1-amd64/build M=/root/work\_1 modules
make\[1]: Entering directory '/usr/src/linux-headers-6.12.74+deb13+1-amd64'
CC \[M] /root/work\_1/vser.o
/root/work\_1/vser.o: warning: objtool: init\_module(): not an indirect call target
/root/work\_1/vser.o: warning: objtool: cleanup\_module(): not an indirect call target
MODPOST /root/work\_1/Module.symvers
ERROR: modpost: missing MODULE\_LICENSE() in /root/work\_1/vser.o
make\[3]: \*\*\* \[/usr/src/linux-headers-6.12.74+deb13+1-common/scripts/Makefile.modpost:145: /root/work\_1/Module.symvers] Error 1
make\[2]: \*\*\* \[/usr/src/linux-headers-6.12.74+deb13+1-common/Makefile:1922: modpost] Error 2
make\[1]: \*\*\* \[/usr/src/linux-headers-6.12.74+deb13+1-common/Makefile:236: \_\_sub-make] Error 2
make\[1]: Leaving directory '/usr/src/linux-headers-6.12.74+deb13+1-amd64'
make: \*\*\* \[Makefile:12: modules] Error 2
其中真正核心的报错信息为
ERROR: modpost: missing MODULE_LICENSE() in /root/work_1/vser.o
Linux要求内核模块进行生命,尤其是MODULE_LICENSE() 。所以我们在我们刚刚的内核模块后面加上MODULE_LICENSE("GPL");,修改后的源码是:
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
int init_module(void)
{
printk("module init\n");
return 0;
}
void cleanup_module(void)
{
printk("cleanup module\n");
}
MODULE_LICENSE("GPL");
修复后,重新编译。
编译成功
如果一切顺利的话,应该会如下图所示(不用管waring)

并且当前工作目录会出现大量新增文件(主要是要看有没有生成vser.ko),如果没有报错,代表生成成功。
加载内核模块
(注意,这些操作需要以root权限运行,当前我登陆账号已经是root账号了)
insmod ./vser.ko
加载完后,输入
dmesg | tail
输出结果如下图

如果有
[ 411.536872] module init
这个就代表成功了(这个内容是我们刚刚的vser.c的printk打印出来的内容)
执行下面命令可以查看是否在模块列表中,结果如下图,如果有值代表加载成功
lsmod | grep vser

卸载内核模块
输入下方命令卸载模块
rmmod vser
卸载后可以输入下方命令
dmesg | tail
可以看到最下面输出结果有cleanup_module,这是我们刚刚定义的卸载时输出的函数。

查看模块信息
在刚刚的文件夹执行
modinfo ./vser.ko
输出
root@iZn4a73i0mqohljrenhyi4Z:~/work_1# modinfo ./vser.ko
filename: /root/work_1/./vser.ko
license: GPL
depends:
name: vser
retpoline: Y
vermagic: 6.12.74+deb13+1-amd64 SMP preempt mod_unload modversions
root@iZn4a73i0mqohljrenhyi4Z:~/work_1#