2. Linux 可加载内核模块简介

如果你想向 Linux 内核添加代码,最基本的方法是将一些源文件添加到内核源代码树并重新编译内核。实际上,内核配置过程主要包括选择要包含在要编译的内核中的文件。

但是你也可以在 Linux 内核运行时向其添加代码。以这种方式添加的代码块称为可加载内核模块。这些模块可以做很多事情,但它们通常是以下三件事之一:1) 设备驱动程序;2) 文件系统驱动程序;3) 系统调用。内核隔离了某些功能,包括这些功能,效果非常好,因此它们不必与内核的其余部分错综复杂地连接在一起。

2.1. 术语

可加载内核模块通常简称为内核模块或模块,但这些术语相当具有误导性,因为世界上有很多种模块,并且构建到基本内核中的各种部分也很容易被称为模块。我们使用术语可加载内核模块或 LKM 来指代本 HOWTO 所涉及的特定类型的模块。

有些人认为 LKM 在内核之外。他们说 LKM 与内核通信。这是一个错误;LKM(加载后)是内核的组成部分。对于绑定到你启动的镜像中的内核部分,即除了 LKM 之外的所有内核,正确的术语是“基本内核”。LKM 与基本内核通信。

在其他一些操作系统中,与 Linux LKM 等效的东西被称为“内核扩展”。

那么什么是 “Linux” 呢?首先,这个名称用于两个完全不同的事物,其中只有一个与这里真正相关

  1. 内核和 Linus Torvalds 以软件包形式分发的相关项目。

  2. 一类传统上基于 Linux 内核的操作系统。

只有第一个定义在讨论 LKM 时真正有用。但即使选择这个定义,人们在谈到 LKM 时也常常感到困惑。LKM 是 Linux 的一部分吗?虽然 LKM 始终是内核的一部分,但如果它在 Linux 内核软件包中分发,它就是 Linux 的一部分,否则就不是。因此,如果你已将设备随附的设备驱动程序 LKM 加载到内核中,严格来说,你不能说你的内核是 Linux。相反,它是 Linux 的一个轻微扩展。正如你可能预料的那样,大约使用名称 “Linux” 是很常见的——Linux 的许多变体正在使用中并被广泛分发,并被称为 “Linux”。不过,在本文档中,为了清晰起见,我们将坚持最严格的定义。

2.2. 可加载内核模块的历史

LKM 最初在 Linux 中不存在。我们今天使用 LKM 的任何东西都是在内核构建时构建到基本内核中的。LKM 至少从 Linux 1.2 (1995) 就已经存在了。

设备驱动程序等一直都非常模块化。当 LKM 被发明时,只需要对这些模块进行少量工作即可使其可构建为 LKM。但是,必须对每个模块都进行此操作,因此需要一些时间。自 2000 年左右以来,几乎所有作为 LKM 有意义的东西至少都具有作为 LKM 的选项。

2.3. 采用可加载内核模块的理由

你通常可以选择通过将模块加载为 LKM 或将其绑定到基本内核中来将模块放入内核。与绑定到基本内核相比,LKM 有很多优势,我建议尽可能使用它们。

一个优点是你不必经常重新构建内核。这节省了你的时间,并避免了在重新构建和重新安装基本内核时引入错误的可能性。一旦你有一个可用的基本内核,最好尽可能长时间地保持其不变。

另一个优点是 LKM 可以帮助你诊断系统问题。绑定到内核中的设备驱动程序中的错误可能会阻止你的系统完全启动。而且很难分辨是基本内核的哪个部分导致了问题。但是,如果同一个设备驱动程序是 LKM,则基本内核会在设备驱动程序加载之前启动并运行。如果你的系统在基本内核启动并运行后死机,那么很容易将问题追溯到导致问题的设备驱动程序,并且在你解决问题之前只需不加载该设备驱动程序即可。

LKM 可以节省你的内存,因为你只需在实际使用它们时才加载它们。基本内核的所有部分始终保持加载状态。并且是在实际存储中,而不仅仅是虚拟存储。

LKM 在维护和调试方面要快得多。对于构建到内核中的文件系统驱动程序需要完全重启才能完成的操作,你可以使用 LKM 的几个快速命令来完成。你可以尝试不同的参数,甚至可以快速连续地反复更改代码,而无需等待启动。

顺便说一句,LKM 并不比基本内核模块慢。调用任何一个都只是分支到它所在的内存位置。[1]

有时你必须将某些东西构建到基本内核中,而不是将其制作为 LKM。任何使系统启动到足以加载 LKM 的东西显然都必须构建到基本内核中。例如,包含根文件系统的磁盘驱动器的驱动程序必须构建到基本内核中。

2.4. LKM 不能做什么

有一种趋势是将 LKM 视为用户空间程序。它们确实具有很多共同的属性,但 LKM 绝对不是用户空间程序。它们是内核的一部分。因此,它们可以自由运行系统并容易使其崩溃。

2.5. LKM 用于什么

LKM 主要用于六件事

注释

[1]

对于喜欢咬文嚼字的人,请参阅第 10.7 节