📜  Linux 可加载内核模块

📅  最后修改于: 2022-05-13 01:57:34.158000             🧑  作者: Mango

Linux 可加载内核模块

如果您想将代码添加到 Linux 工具包中,基本的方法是将源文件添加到内核源代码树并组装内核。实际上,设置内核的过程主要包括选择将哪些文件上传到内核将被合并。但您也可以在 Linux 工具包运行时向它添加代码。您以这种方式添加的一段代码称为可加载内核模块 (LKM) 。这些模块可以做很多事情,但它们通常是以下三个项目之一:

  • 设备驱动程序
  • 文件系统驱动程序
  • 系统调用。

内核分离了某些功能,包括这些功能,特别好,因此不需要跨内核加密。驱动程序必须知道的几个参数可以改变系统。这些可能会有所不同,从要使用的设备编号到驱动程序应该如何操作的许多方面。

术语

可下载的内核模块通常被称为内核模块或仅称为模块,但它们具有误导性,因为世界上有如此多类型的模块,它们内置在基本内核中的不同部分很容易被称为模块。对于某些类型的模块,我们使用术语内核模块或 LKM。有些人认为 LKM 在内核之外。他们谈论连接到内核的 LKM。这是个错误; LKM(如果已加载)是内核的很大一部分。与您正在启动的映像相关联的部分内核的正确术语是“基本内核”。 LKM 连接到基本内核。在某些操作系统中,相当于 Linux LKM 的称为“内核扩展”。

LKM的历史

可加载内核模块最初不在 Linux 中。我们今天用于 LKM 的任何东西都是在构建内核时内置到基础内核中的。 LKM 至少从 Linux 1.2 (1995) 就已经存在。然而,设备驱动程序等总是模块化的。建立 LKM 时,需要对这些模块进行少量工作以形成 LKM。然而,它必须单独完成,所以需要时间。大约从 2000 年开始,几乎所有像 LKM 这样明智的人都至少可以选择成为 LKM。

LKM 的案例

您通常可以选择通过将模块作为 LKM 上传或提交到内核中来安装模块。基础内核。 LKM 除了绑定到基本内核之外还有很多好处。另一个优点是您不需要经常重建内核。这样可以节省时间并节省您的时间。您可能在重组和改进基本内核时犯了错误。一旦你有了一个工作基础内核,最好尽可能长时间地保持不变。另一个优点是 LKM 可以帮助您诊断系统问题。中断内核中的设备驱动程序可能会完全停止您的系统运行。而且很难说基础内核的哪一部分造成了问题。但是,如果同一 LKM 设备的驱动程序,则在加载设备驱动程序之前,基本内核会再次处于活动状态。一旦您打开/关闭基本内核直到设备驱动程序导致问题并且我们在解决问题之前不会加载设备驱动器,当您的系统死机时,很容易跟踪问题。

LKM 可以节省您的内存,因为您只有在真正使用它们时才应该下载它们。基本内核的所有部分都在任何时候都被加载——在真实存储中,而不是虚拟存储中。 LKM 的维护和维修速度非常快。使用内核中内置的文件系统驱动程序可能需要完全重启才能完成,您可以使用 LKM 的一些快速命令来完成。您可以快速连续尝试不同的参数或重复更改代码,而无需等待启动。顺便说一下,LKM 比基本内核模块做得更少。在任何地方调用只是它所在的内存位置的一个分支。有时您必须在基本内核中构建一些东西,而不是使其成为 LKM。显然,将系统移动到足以加载 LKM 所需的任何东西都应该内置到基本内核中。

LKM 用于什么?

让我们看看使用的主要 6 个 LKM。

  • 设备驱动程序:设备驱动程序是为特定的硬件设计的。内核使用它来联系该硬件,而不知道它工作的任何硬件细节。例如,有一个 ATA 磁盘驱动器设备驱动程序。有一个用于 NE2000 兼容的以太网卡。为了使用任何设备,内核必须包含其设备的驱动程序。
  • 文件系统驱动程序:文件系统驱动程序解释文件系统的内容,例如文件和引用等。有很多方法可以保存文件和参考。无论如何,您需要一个文件系统驱动程序。例如,有一个 ext2 文件类型的文件系统驱动程序几乎全世界都在 Linux 磁盘驱动器上使用。还有一个 MS-DOS 文件系统,以及一个 NFS。
  • 系统调用:用户空间应用程序使用系统调用来访问内核中的资源。例如,有读取文件、创建新进程和关闭程序的系统调用。大多数系统电话都是系统的一部分并且是最先进的,因此它们总是内置在基本内核中(没有 LKM 选项)。但是您可以配置您的系统电话并将其安装为 LKM。或者你可以决定你不喜欢 Linux 做某事的方式并使用你的 LKM 发出一个现有的系统调用。
  • 网络驱动程序:网络运算符解释网络协议。它在内核通信活动的各个阶段提供和使用数据流。例如,如果您想要一个 IPX 链接到您自己的网络,您将使用 IPX 驱动程序。
  • TTY 线路说明:这实际上是对存储设备的设备驱动程序的升级。
  • 有用的口译员:可用的翻译员上传并使用可用的。 Linux 被设计成能够以多种格式使用,并且每种格式都必须有自己的可用翻译器。

编译内核模块

下面的例子展示了我们的内核模块如何在加载时通过insmodmodprobe 命令从用户那里获取参数。

示例代码:

C++
#include 
#include 
#include 
  
static char* whoisthis = "Mommy";
static int countpeople = 1;
  
module_param(countpeople, int, S_IRUGO);
module_param(whoisthis, charp, S_IRUGO);
  
static int __init m_init(void)
{
    pr_debug("parameters test module is loaded\n");
    for (int i = 0; i < countpeople; ++i) {
        pr_info("#%d Hello, %s\n", i, whoisthis);
    }
    return 0;
}
  
static void __exit m_exit(void)
{
    pr_debug("parameters test module is unloaded\n");
}
  
module_init(m_init);
module_exit(m_exit);
M ODULE_LICENSE("GPL");


贝壳 :

构建模块。要构建此模块,请执行:

如果您已经设置并导出了 `KERNELDIR` 环境变量,只需执行 ` make`就足够了。

用法 :

将目标文件 **hello_world.ko** 复制到目标机器,然后运行:

bash insmod module_parameters.ko

运行`dmesg | tail -10`,你可以找到这样的东西:

没错,我们默认设置为只打印一次**hello, Mommy**。接下来,我们卸载这个模块并在加载时将参数传递给它。

这一次,消息发生了变化:

[ 1322.364784] parameters test module is loaded
[ 1322.366768] #0 Hello, dady
[ 1322.367999] #1 Hello, dady
[ 1322.369154] #2 Hello, dady