编译自己的第一个Linux内核模块

前言

本文记录了下我在学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# 

--------------

本文标题为:

编译自己的第一个Linux内核模块

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇