如果你想向 Linux 内核添加代码,最基本的方法是将一些源文件添加到内核源代码树并重新编译内核。实际上,内核配置过程主要包括选择要包含在要编译的内核中的文件。
但是你也可以在 Linux 内核运行时向其添加代码。以这种方式添加的代码块称为可加载内核模块。这些模块可以做很多事情,但它们通常是以下三件事之一:1) 设备驱动程序;2) 文件系统驱动程序;3) 系统调用。内核隔离了某些功能,包括这些功能,效果非常好,因此它们不必与内核的其余部分错综复杂地连接在一起。
可加载内核模块通常简称为内核模块或模块,但这些术语相当具有误导性,因为世界上有很多种模块,并且构建到基本内核中的各种部分也很容易被称为模块。我们使用术语可加载内核模块或 LKM 来指代本 HOWTO 所涉及的特定类型的模块。
有些人认为 LKM 在内核之外。他们说 LKM 与内核通信。这是一个错误;LKM(加载后)是内核的组成部分。对于绑定到你启动的镜像中的内核部分,即除了 LKM 之外的所有内核,正确的术语是“基本内核”。LKM 与基本内核通信。
在其他一些操作系统中,与 Linux LKM 等效的东西被称为“内核扩展”。
那么什么是 “Linux” 呢?首先,这个名称用于两个完全不同的事物,其中只有一个与这里真正相关
内核和 Linus Torvalds 以软件包形式分发的相关项目。
一类传统上基于 Linux 内核的操作系统。
只有第一个定义在讨论 LKM 时真正有用。但即使选择这个定义,人们在谈到 LKM 时也常常感到困惑。LKM 是 Linux 的一部分吗?虽然 LKM 始终是内核的一部分,但如果它在 Linux 内核软件包中分发,它就是 Linux 的一部分,否则就不是。因此,如果你已将设备随附的设备驱动程序 LKM 加载到内核中,严格来说,你不能说你的内核是 Linux。相反,它是 Linux 的一个轻微扩展。正如你可能预料的那样,大约使用名称 “Linux” 是很常见的——Linux 的许多变体正在使用中并被广泛分发,并被称为 “Linux”。不过,在本文档中,为了清晰起见,我们将坚持最严格的定义。
LKM 最初在 Linux 中不存在。我们今天使用 LKM 的任何东西都是在内核构建时构建到基本内核中的。LKM 至少从 Linux 1.2 (1995) 就已经存在了。
设备驱动程序等一直都非常模块化。当 LKM 被发明时,只需要对这些模块进行少量工作即可使其可构建为 LKM。但是,必须对每个模块都进行此操作,因此需要一些时间。自 2000 年左右以来,几乎所有作为 LKM 有意义的东西至少都具有作为 LKM 的选项。
你通常可以选择通过将模块加载为 LKM 或将其绑定到基本内核中来将模块放入内核。与绑定到基本内核相比,LKM 有很多优势,我建议尽可能使用它们。
一个优点是你不必经常重新构建内核。这节省了你的时间,并避免了在重新构建和重新安装基本内核时引入错误的可能性。一旦你有一个可用的基本内核,最好尽可能长时间地保持其不变。
另一个优点是 LKM 可以帮助你诊断系统问题。绑定到内核中的设备驱动程序中的错误可能会阻止你的系统完全启动。而且很难分辨是基本内核的哪个部分导致了问题。但是,如果同一个设备驱动程序是 LKM,则基本内核会在设备驱动程序加载之前启动并运行。如果你的系统在基本内核启动并运行后死机,那么很容易将问题追溯到导致问题的设备驱动程序,并且在你解决问题之前只需不加载该设备驱动程序即可。
LKM 可以节省你的内存,因为你只需在实际使用它们时才加载它们。基本内核的所有部分始终保持加载状态。并且是在实际存储中,而不仅仅是虚拟存储。
LKM 在维护和调试方面要快得多。对于构建到内核中的文件系统驱动程序需要完全重启才能完成的操作,你可以使用 LKM 的几个快速命令来完成。你可以尝试不同的参数,甚至可以快速连续地反复更改代码,而无需等待启动。
顺便说一句,LKM 并不比基本内核模块慢。调用任何一个都只是分支到它所在的内存位置。[1]
有时你必须将某些东西构建到基本内核中,而不是将其制作为 LKM。任何使系统启动到足以加载 LKM 的东西显然都必须构建到基本内核中。例如,包含根文件系统的磁盘驱动器的驱动程序必须构建到基本内核中。
LKM 主要用于六件事
设备驱动程序。设备驱动程序是为特定硬件设计的。内核使用它与该硬件通信,而无需了解硬件如何工作的任何细节。例如,有用于 ATA 磁盘驱动器的设备驱动程序。有一个用于 NE2000 兼容以太网卡的驱动程序。要使用任何设备,内核必须包含该设备的设备驱动程序。
文件系统驱动程序。文件系统驱动程序将文件系统(通常是磁盘驱动器的内容)的内容解释为文件和目录等。有很多不同的方法可以在磁盘驱动器、网络服务器和其他方式上存储文件和目录等。对于每种方式,你都需要一个文件系统驱动程序。例如,有一个用于 ext2 文件系统类型的文件系统驱动程序,该类型几乎普遍用于 Linux 磁盘驱动器。还有一个用于 MS-DOS 文件系统的驱动程序,以及一个用于 NFS 的驱动程序。
系统调用。用户空间程序使用系统调用从内核获取服务。例如,有用于读取文件、创建新进程和关闭系统的系统调用。大多数系统调用是系统不可或缺的并且非常标准,因此始终构建到基本内核中(没有 LKM 选项)。但是你可以发明自己的系统调用并将其安装为 LKM。或者你可以决定你不喜欢 Linux 的某些操作方式,并使用你自己的 LKM 覆盖现有的系统调用。
网络驱动程序。网络驱动程序解释网络协议。它在内核网络功能的各个层面上馈送和消耗数据流。例如,如果要在网络中使用 IPX 链接,则可以使用 IPX 驱动程序。
TTY 线路规程。这些本质上是终端设备设备驱动程序的增强功能。
可执行解释器。可执行解释器加载并运行可执行文件。Linux 旨在能够运行各种格式的可执行文件,并且每种格式都必须有自己的可执行解释器。
[1] | 对于喜欢咬文嚼字的人,请参阅第 10.7 节。 |