如何创建、编译、加载 Linux LKM 可加载内核模块

举报
Tiamo_T 发表于 2022/06/13 16:06:24 2022/06/13
【摘要】 假设我们想在 Linux 内核中添加一些额外的功能。因此,首先想到的是通过向内核添加更多代码、编译代码并启动新内核来增强内核。但是这个过程有以下几个缺点:添加的代码会永久增加内核的大小。整个内核需要再次编译才能编译更改。这意味着需要重新启动机器才能使更改生效。上述问题的解决方案就是 LKM 的概念。LKM 代表可加载内核模块 (LKM)。顾名思义,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 内核中工作。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。