如何创建、编译、加载 Linux LKM 可加载内核模块
假设我们想在 Linux 内核中添加一些额外的功能。
因此,首先想到的是通过向内核添加更多代码、编译代码并启动新内核来增强内核。
但是这个过程有以下几个缺点:
- 添加的代码会永久增加内核的大小。
- 整个内核需要再次编译才能编译更改。
- 这意味着需要重新启动机器才能使更改生效。
上述问题的解决方案就是 LKM 的概念。
LKM 代表可加载内核模块 (LKM)。顾名思义,LKM 是可以在运行时直接加载到内核中的模块。
可加载内核模块克服了上述所有缺点。
- 模块可以单独编译
- 该模块可以在运行时加载到内核中,而无需重新启动机器。
- 该模块可以随时卸载,因此对内核大小没有永久影响。
如何创建 LKM
让我们创建一个基本的可加载内核模块。
#include <linux/module.h>
#include <linux/kernel.h>
int init_module(void)
{
printk(KERN_INFO "Welcome.....\n");
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Bye....\n");
}
所以我们看到上面的代码是一个基本的LKM。
- 名称“init_module”和“cleanup_module”是 LKM 的标准名称。
- 如果您仔细观察,您会发现我们使用了“printk”而不是“printf”。这是因为它不是普通的 C 编程,它是内核级编程,与普通用户级编程有点不同。
- 必须包含头文件 module.h 和 kernel.h 才能编译代码。
如何编译 LKM
为了编译上述 LKM,我使用了以下 Makefile :
obj-m += lkm.o
all:
sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
sudo make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
请注意,上面以关键字 'sudo' 开头的命令应该从左边算起一个制表符空格。
因此,当运行上述命令时,会观察到以下输出:
make: Entering directory `/usr/src/linux-headers-2.6.32-21-generic'
CC [M] /home/himanshu/practice/lkm.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/himanshu/practice/lkm.mod.o
LD [M] /home/himanshu/practice/lkm.ko
make: Leaving directory `/usr/src/linux-headers-2.6.32-21-generic'
上述编译成功后,您将在编译发生的同一目录中找到一个 .ko 文件。
这个 .ko 文件是将加载到内核中的模块。modinfo 实用程序可用于获取有关此模块的信息:
$ modinfo lkm.ko
filename: lkm.ko
srcversion: 19967CB3EAB7B31E643E006
depends:
vermagic: 2.6.32.11+drm33.2 SMP mod_unload modversions
所以我们看到实用程序“modinfo”提供了一些关于这个模块的信息。
LKM 是如何加载的
在成功编译和创建模块之后,现在是时候将其插入内核,以便在运行时加载它。可以使用以下两个实用程序来实现模块的插入:
- 模组探针
- 安装模块
两者之间的区别在于“modprobe”处理这样一个事实,即如果模块依赖于其他模块,则首先加载该模块,然后加载主模块。而“insmod”实用程序只是将模块(指定名称)插入内核。
所以'modprobe'是一个更好的实用程序,但由于我们的模块不依赖于任何其他模块,所以我们将只使用'insmod'。
因此,要插入模块,请使用以下命令:
$ sudo insmod ./lkm.ko
如果此命令没有给出任何错误,则表示 LKM 已成功加载到内核中。
要卸载 LKM,请使用以下命令:
$ sudo rmmod lkm.co
同样,如果此命令没有给出任何错误,则意味着 LKM 已成功卸载到内核中。
要检查模块是否正确加载和卸载,我们可以使用dmesg 实用程序,它提供内核记录的最后一组日志。您将在所有其他日志中看到以下两行:
....
....
[ 4048.333756] Welcome.....
[ 4084.205143] Bye....
如果你回到代码看,你会发现这些是代码中两个函数的日志。
因此,我们看到调用“insmod”时调用了一个函数,而调用“rmmod”时调用了另一个函数。
这只是一个虚拟的 LKM。通过这种方式,许多工作的 LKM(执行有意义的任务)在 Linux 内核中工作。
- 点赞
- 收藏
- 关注作者
评论(0)