12. Linux 版本之间的差异

在本节中值得一提的是,世界上存在各种各样的 Linux 版本以及我们如何称呼它们。与一家公司仔细控制名称并创建少量明确定义的版本的专有软件产品不同,Linux 的变体是由许多不同的独立人士开发的,并且都称为 Linux。

最基本的 Linux 版本由 Linus Torvalds 控制,并通过 kernel.org 作为主要的 Linux 版本发布。它们是唯一可以正确地称为“Linux 2.4”、“Linux 2.6.6”等的版本。

但几乎没有人使用这些版本。相反,人们从这些版本开始并进行修改。人们经常草率地将基于 Linux 2.6.6 的 Linux 称为 Linux 2.6.6 本身。但为了正确起见,您必须添加一些内容——通常是连字符和后缀。您经常看到的 Red Hat 版本的 Linux 不幸地仅使用纯数字作为后缀,例如 Linux 2.6.6-12。(如果他们使用更明确的 Red Hat 标识会更好,例如 Linux 2.6.6-rh12)。

请记住,在本文档中,“Linux”指的是内核;当我们考虑称为“Linux”的操作系统时,情况会变得更加复杂。

12.1. Linux 2.4 - Linux 2.6

12.1.1. 在内核中完成链接

Linux 2.4 和 Linux 2.6 之间 LKM 的最大变化是内部的:LKM 的加载方式大不相同。大多数人不会看到任何区别,除了包含 LKM 的文件后缀已更改,因为他们使用高级工具来管理 LKM,并且这些工具的接口没有改变。

在 Linux 2.6 之前,用户空间程序会解释 ELF 对象 (.o) 文件,并完成将其链接到正在运行的内核的所有工作,从而生成一个完成的二进制映像。该程序会将该映像传递给内核,而内核所做的只是将其放入内存中。在 Linux 2.6 中,内核执行链接。用户空间程序将 ELF 对象文件的内容直接传递给内核。为了使其工作,ELF 对象映像必须包含附加信息。为了标识这种特定的 ELF 对象文件,我们将文件命名为后缀“.ko”(“内核对象”),而不是“.o”。例如,在 Linux 2.4 中,串行设备驱动程序位于文件serial.o在 Linux 2.6 中,它位于文件serial.ko.

因此,有一个全新的 modutils 包用于 Linux 2.6。其中,与 Linux 2.4 版本的完整链接器相比,insmod 是一个简单的程序。

此外,构建 LKM 的过程也更加困难。要创建 .ko 文件,您首先需要一个常规的 .o 文件。您在其上运行程序 modpost(随 Linux 源代码一起提供),以创建一个 C 源文件,该文件描述 .ko 文件所需的附加部分。我们将此称为 .mod 文件,因为您通常在文件名中包含“.mod”。

您编译 .mod 文件并将结果与原始 .o 文件链接以创建 .ko 文件。

.mod 对象文件包含加载 LKM 时 LKM 实例将具有的名称。您可以使用 -D 编译选项(在编译 .mod 文件时)设置该名称,该选项设置 KBUILD_MODNAME 宏。

此更改意味着有些事情明显变得更加困难——例如,选择 LKM 实例的名称。在 Linux 2.4 中,该名称是内核的输入之一。insmod 决定了名称并将其传递给内核。insmod 的 -o 选项明确告知它要用于 LKM 实例名称的名称。但在 2.6 中,系统调用上没有这样的参数,因此 insmod 上也没有 -o 选项。该名称是您传递给内核的 ELF 对象(.o 文件)的一部分。默认名称内置于 ELF 对象中,但如果您想使用其他名称加载它,则必须在将其传递给 insmod 之前编辑 ELF 映像。

12.1.2. 没有模块繁忙函数

在 Linux 2.6 中can_unload(参见 第 11.4 节)已消失。

12.1.3. CONFIG_MODULE_UNLOAD

您可以配置内核构建以构建一个完全不允许卸载模块的内核,从而避免模块在使用时被卸载的任何问题。请参见 第 11.4 节

12.1.4. 引用计数

LKM 代码用于操作其引用计数的接口已被替换。