Linux 可加载内核模块 HOWTO

Bryan Henderson

2006-09-24

修订历史
版本 v1.092006-09-24修订者: bjh
修复拼写错误。
版本 v1.082006-03-03修订者: bjh
添加版权信息。
版本 v1.072005-07-20修订者: bjh
添加一些 2.6 的信息和免责声明。更新对 Linux 设备驱动程序书籍、Linux 内核模块编程指南的引用。
版本 v1.062005-01-12修订者: bjh
简要介绍 Linux 2.6。更新 hello.c 并引用 Lkmpg。添加关于卸载危险的信息。提及 dmesg 作为查看内核消息的方式。
版本 v1.052004-01-05修订者: bjh
添加关于 module.h 和 -DMODULE 的信息。修复 tldb.org 为 tldp.org。添加关于 kallsyms 的信息。
版本 v1.042003-10-10修订者: bjh
修复拼写错误:AHA154x 应该为 AHA152x。添加关于内核模块加载器调用的模块名称的信息。添加关于首次加载 LKM 时 LKM 所做的事情的信息。添加关于 loop 模块的信息。将 linuxdoc.org 更改为 tldp.org。
版本 v1.032003-07-03修订者: bjh
更新关于不加载到 vmalloc 空间的内核。添加 LKM 的“已删除”状态的解释。解释 GPLONLY。
版本 v1.022002-05-21修订者: bjh
更正符号版本控制的解释。更正 Linux 设备驱动程序的作者。添加 LKM 相对于绑定编译的内存分配惩罚信息。添加 LKM 到 LKM 符号匹配的要求。添加 LKM 符号解析中的开源许可问题。添加 SMP 符号版本控制信息。
版本 v1.012001-08-18修订者: bjh
添加关于过去几年创建的各种功能的材料:内核模块加载器、ksymoops 符号、内核版本相关的 LKM 文件位置。
版本 v1.002001-06-14修订者: bjh
初始发布。

这是 Linux 可加载内核模块 (LKM) 的 HOWTO。 它解释了它们是什么以及如何使用和创建它们。 它还包括一些特定模块的参数和其他使用细节的文档。


目录
1. 前言
2. Linux 可加载内核模块介绍
2.1. 术语
2.2. 可加载内核模块的历史
2.3. 可加载内核模块的理由
2.4. LKM 不能做什么
2.5. LKM 的用途
3. 制作可加载内核模块
4. LKM 实用程序
5. 如何插入和删除 LKM
5.1. 找不到内核版本...
5.2. LKM 加载时会发生什么
5.3. 智能加载 LKM - Modprobe
5.4. 自动 LKM 加载和卸载
5.5. /proc/modules
5.6. 我的 LKM 文件在系统上的什么位置?
6. 未解析的符号
6.1. 一些 LKM 预先需要其他 LKM
6.2. LKM 必须与基本内核匹配
6.3. 如果您运行多个内核
6.4. SMP 符号
6.5. 您未获得访问该符号的许可
6.6. LKM 必须与先决条件的 LKM 匹配
7. 如何在没有磁盘设备驱动程序的情况下启动
8. 关于模块参数
9. 持久数据
10. 技术细节
10.1. 它们如何工作
10.2. .modinfo 节
10.3. __ksymtab 和 .kstrtab 节
10.4. Ksymoops 符号
10.5. 其他符号
10.6. 调试符号
10.7. 加载的内存分配
10.8. Linux 内部机制
11. 编写您自己的可加载内核模块
11.1. 更简单的 hello.c
11.2. 使用内核构建系统
11.3. Rubini et al: Linux 设备驱动程序
11.4. 模块使用计数
12. Linux 版本之间的差异
12.1. Linux 2.4 - Linux 2.6
13. LKM 的版权考虑
14. 相关文档
15. 单独的模块
15.1. 可执行解释器
15.2. 块设备驱动程序
15.3. SCSI 驱动程序
15.4. 网络设备驱动程序
15.5. CDROM 设备驱动程序
15.6. 文件系统驱动程序
15.7. 其他设备驱动程序
15.8. 串行设备驱动程序
15.9. 并行设备驱动程序
15.10. 总线鼠标设备驱动程序
15.11. 磁带设备驱动程序
15.12. 看门狗定时器
15.13. 声音设备驱动程序
16. 本文档的维护
17. 历史
18. 版权

1. 前言

版权和许可信息以及致谢,都在本文档的末尾。

本 HOWTO 由 Bryan Henderson, bryanh@giraffe-data.com 维护。您可以从 Linux 文档项目获取本 HOWTO 的当前版本。

本文档主要针对 Linux 2.4。它也次要地涵盖了早期的 Linux。它仅部分涵盖了更新的 Linux,但作者的目标是在未来的版本中完全涵盖它。 特别是参见 第 12 节。 该主题在 Linux 2.5 版本的过程中发生了很大变化,本文档忽略了 2.5,因为 2.5 版本未被视为生产版本。 相反,本文档将 2.5 版本中的所有更改都视为 Linux 2.6 的新特性。

参见 第 17 节 以了解文档的历史。


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 被发明时,只需要对这些模块进行少量工作即可使它们可作为 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 主要用于以下六个方面:

  • 设备驱动程序。 设备驱动程序是为特定的硬件设计的。内核使用它与该硬件进行通信,而无需了解硬件如何工作的任何细节。例如,有用于 ATA 磁盘驱动器的设备驱动程序。还有一个用于 NE2000 兼容以太网卡的驱动程序。要使用任何设备,内核必须包含该设备的设备驱动程序。

  • 文件系统驱动程序。 文件系统驱动程序将文件系统的内容(通常是磁盘驱动器的内容)解释为文件和目录等。 有很多不同的方法可以在磁盘驱动器、网络服务器和其他方式上存储文件和目录等。 对于每种方法,您都需要一个文件系统驱动程序。 例如,有一个用于 ext2 文件系统类型的驱动程序,该文件系统类型几乎普遍用于 Linux 磁盘驱动器上。 还有一个用于 MS-DOS 文件系统的驱动程序,以及一个用于 NFS 的驱动程序。

  • 系统调用。 用户空间程序使用系统调用从内核获取服务。 例如,有读取文件、创建新进程和关闭系统的系统调用。 大多数系统调用都是系统不可或缺且非常标准的,因此始终构建到基本内核中(没有 LKM 选项)。 但是您可以发明自己的系统调用并将其作为 LKM 安装。 或者,您可以决定您不喜欢 Linux 的某些行为,并使用您自己的 LKM 覆盖现有的系统调用。

  • 网络驱动程序。 网络驱动程序解释网络协议。 它在内核网络功能的各个层级上提供和使用数据流。 例如,如果您希望在网络中使用 IPX 链接,您将使用 IPX 驱动程序。

  • TTY 行规程。 这些本质上是对终端设备设备驱动程序的增强。

  • 可执行文件解释器。 可执行文件解释器加载并运行可执行文件。 Linux 被设计为能够以各种格式运行可执行文件,并且每个格式必须有其自己的可执行文件解释器。


3. 制作可加载内核模块

LKM 存在于单个 ELF 对象文件中(通常命名为 "serial.o")。 通常,您将所有 LKM 对象文件保存在特定目录中(靠近您的基本内核镜像是有意义的)。 当您使用 insmod 程序将 LKM 插入到内核中时,您需要提供该对象文件的名称。

对于作为 Linux 一部分的 LKM,您可以将它们作为生成基本内核镜像的同一内核构建过程的一部分来构建。 请参阅 Linux 源代码树中的 README 文件。 简而言之,在使用诸如 make zImage 之类的命令制作基本内核镜像之后,您将使用以下命令制作所有 LKM:

make modules     

这会在整个 Linux 源代码树中生成一堆 LKM 对象文件 (*.o)。 (在旧版本的 Linux 中,Linux 源代码树的modules目录中将会有指向所有这些 LKM 对象文件的符号链接)。 这些 LKM 已经准备好加载,但您可能希望将它们安装在某些适当的目录中。 传统位置在 第 5.6 节中描述。 make modules_install 命令会将它们全部复制到传统位置。

配置 Linux 内核(在构建时)的一部分是选择将内核的哪些部分绑定到基本内核中,以及将哪些部分生成为单独的 LKM。 在基本问答配置 (make config) 中,系统会询问您,对于内核的每个可选部分,您是希望将其绑定到内核中(“Y”响应),创建为 LKM(“M”响应),还是完全跳过(“N”响应)。 其他配置方法类似。

第 2.3 节中所述,您应该只将最少的部分绑定到基本内核中。 并且只完全跳过您确定永远不需要的部分。 构建一个您不会使用的 LKM 几乎没有什么损失。 一些编译时间、一些磁盘空间、代码中出现问题导致内核构建失败的几率。 仅此而已。

作为配置对话框的一部分,您还必须选择是否使用符号版本控制。 此选择会影响基本内核和 LKM 的构建,并且至关重要的是要正确处理。 请参阅 第 6 节

不属于 Linux 的 LKM(即未与 Linux 内核一起分发)具有其自己的构建过程,我将不进行介绍。 但是,任何此类过程的目标始终是最终得到一个 ELF 对象文件。

您不必同时重建所有 LKM 和基本内核镜像(例如,您可以只构建基本内核,并使用您之前构建的 LKM),但始终是一个好主意。 请参阅 第 6 节


4. LKM 实用程序

您需要加载、卸载和以其他方式处理 LKM 的程序都在 modutils 包中。 您可以在 此目录中找到此包。

此包包含以下程序来帮助您使用 LKM:

insmod

将 LKM 插入到内核中。

rmmod

从内核中删除 LKM。

depmod

确定 LKM 之间的相互依赖关系。

kerneld

Kerneld 守护程序

ksyms

显示内核导出的符号,供新的 LKM 使用。

lsmod

列出当前已加载的 LKM。

modinfo

显示.modinfoLKM 对象文件中的 section 的内容。

modprobe

智能地插入或删除 LKM 或 LKM 集。 例如,如果您必须先加载 A 才能加载 B,则当您告诉 Modprobe 加载 B 时,它将自动加载 A。

对内核的更改通常需要对 modutils 进行更改,因此请确保在升级内核时使用当前版本的 modutilsmodutils 始终向后兼容(它可以与旧内核一起使用),因此拥有太新的 modutils 没什么坏处。

警告:modprobe 调用 insmod,其位置硬编码为/sbin/insmodmodutils 中可能存在其他不使用 PATH 查找程序的情况。 因此,请在构建 modutils 之前修改其源代码,或者确保将程序安装在它们的传统目录中。


5. 如何插入和删除 LKM

用于插入和删除 LKM 的基本程序是 insmodrmmod。 有关详细信息,请参阅它们的手册页。

插入 LKM 在概念上很简单:只需以超级用户身份输入诸如

insmod serial.o
(serial.o包含串行端口 (UART) 的设备驱动程序)。

但是,如果我说该命令可以正常工作,那就太具有误导性了。 该命令非常容易失败,并且非常令人恼火,要么出现关于模块/内核版本不匹配的消息,要么出现一堆未解析的符号。

但是,如果它确实有效,那么证明您知道自己在做什么的方法是查看/proc/modules第 5.5 节中所述。

请注意,本节中的示例来自 Linux 2.4。 在 Linux 2.6 中,加载 LKM 的技术方面有很大不同,最明显的表现是 LKM 文件的后缀为 ".ko" 而不是 ".o"。 但是,从用户的角度来看,它看起来非常相似。

现在让我们看一个更困难的插入。 如果你尝试

insmod msdos.o
您可能会收到大量错误消息,例如
  msdos.o: unresolved symbol fat_date_unix2dos
  msdos.o: unresolved symbol fat_add_cluster1
  msdos.o: unresolved symbol fat_put_super
  ...

这是因为 msdos.o 包含对所提及符号的外部符号引用,并且内核没有导出这些符号。 为了证明这一点,请执行

cat /proc/ksyms
以列出内核导出的每个符号(即,可用于绑定到 LKM)。 您将看到“fat_date_unix2dos”不在列表中。

(在 Linux 2.6 中,没有/proc/ksyms。 使用/proc/kallsyms代替;格式类似于 nm 的输出:查找标记为 "t" 的符号)。

如何将其放入列表中? 通过加载另一个 LKM,一个定义这些符号并导出它们的 LKM。 在本例中,它是文件中的 LKMfat.o。 所以做

  insmod fat.o
然后查看 "fat_date_unix2dos" 是否在/proc/ksyms。 现在重做
insmod msdos.o
它就能工作了。 看一下/proc/modules并查看两个 LKM 都已加载,并且一个依赖于另一个
msdos                   5632   0 (unused)
fat                    30400   0 [msdos]

我是怎么知道fat.o是我缺少的模块? 只需一点独创性。 解决此问题的更稳健方法是使用 depmodmodprobe 而不是 insmod,如下所述。

当您的符号看起来像 "fat_date_unix2dos_R83fb36a1" 时,问题可能比仅仅加载先决条件 LKM 更复杂。 请参阅 第 6 节

当错误消息为“kernel/module version mismatch”时,请参阅 第 6 节

通常,您需要在插入 LKM 时将参数传递给它。 例如,设备驱动程序想要知道它应该驱动的设备的地址和 IRQ。 或者,网络驱动程序想要知道您希望它执行多少诊断跟踪。 这是一个例子

insmod ne.o io=0x300 irq=11

在这里,我正在加载我的 NE2000 类以太网适配器的设备驱动程序,并告诉它驱动 IO 地址为 0x300 的以太网适配器,该地址在 IRQ 11 上生成中断。

LKM 没有标准参数,也很少有约定。 每个 LKM 作者决定 insmod 将为其 LKM 采用哪些参数。 因此,您将在 LKM 的文档中找到它们。 本 HOWTO 还在 第 15 节中汇编了大量 LKM 参数信息。 有关 LKM 参数的一般信息,请参阅 第 8 节

要从内核中删除 LKM,命令类似于

rmmod ne

有一个命令 lsmod 可以列出当前已加载的 LKM,但它所做的只是转储/proc/modules的内容,带有列标题,因此您可能只想直接访问来源并忘记 lsmod


5.1. 找不到内核版本...

一个常见的错误是尝试插入一个不是 LKM 的对象文件。 例如,您配置内核以使 USB 核心模块绑定到基本内核中,而不是生成为 LKM。 在这种情况下,您最终会得到一个文件usbcore.o,它看起来与您将其构建为 LKM 时得到的usbcore.o非常相似。 但是您不能 insmod 该文件。

那么您是否会收到一条错误消息,告诉您应该配置内核以使 USB 核心功能成为 LKM? 当然不会。 这是 Unix,并且解释性错误消息被视为弱点。 错误信息是

$ insmod usbcore.o
usbcore.o: couldn't find the kernel version this module was compiled for

insmod 告诉您的是,它在usbcore.o中查找了任何合法的 LKM 都应该具有的信息 -- LKM 旨在使用的内核版本 -- 但没有找到它。 我们现在知道它没有找到它的原因是该文件不是 LKM。 有关您如何查看 insmod 正在看到的内容并确认该文件实际上不是 LKM 的信息,请参阅 第 10.2 节

如果这是您自己创建的模块,并且打算将其作为LKM(可加载内核模块)使用,那么您需要问的下一个问题是:为什么它不是一个LKM?最常见的原因是您没有包含linux/module.h在您的源代码顶部,并且/或者没有定义MODULE>宏。MODULE旨在通过编译命令设置 (-DMODULE),并确定编译是生成 LKM 还是用于绑定到基础内核的目标文件。如果您的模块像大多数现代模块一样,只能作为 LKM 构建,那么您应该直接在源代码中定义它 (#define MODULE),然后再包含include/module.h.


5.2. LKM加载时会发生什么

假设您已经成功加载了一个LKM,并通过以下方式验证了它:/proc/modules。但是,您如何知道它是否在工作?这取决于LKM本身,并且根据LKM的类型而有所不同,但以下是LKM加载时的一些常见操作。

设备驱动程序LKM在加载后(如果模块在启动时绑定到基础内核,也会执行此操作)首先通常会在系统中搜索它知道如何驱动的设备。具体的搜索方式因驱动程序而异,并且通常可以通过模块参数进行控制。但无论如何,如果驱动程序没有找到任何它能够驱动的设备,它会导致加载失败。否则,驱动程序会注册自己作为特定主设备号的驱动程序,您可以通过指定该主设备号的设备特殊文件开始使用它找到的设备。它也可能注册自己作为设备使用的中断级别的处理程序。它也可能向设备发送设置命令,因此您可能会看到灯闪烁或类似情况。

您可以在文件/proc/devices中看到设备驱动程序已注册自身。您可以在/proc/interrupts.

中看到设备驱动程序正在处理设备的中断。一个优秀的设备驱动程序会发出内核消息,说明它找到了哪些设备并准备驱动。(在大多数系统中,内核消息最终会出现在控制台和文件/var/log/messages中。您还可以使用 dmesg 程序显示最近的消息)。然而,有些驱动程序是静默的。一个优秀的设备驱动程序还会(在内核消息中)在它未能找到设备时给出其搜索的一些细节,但许多驱动程序只是在没有解释的情况下加载失败,而您得到的只是来自 insmod 的一些关于可能存在的问题的猜测。

网络设备(接口)驱动程序的工作方式类似,只不过LKM注册了一个它选择的设备名称(例如eth0),而不是主设备号。您可以在/proc/net/dev

中看到当前注册的网络设备名称。文件系统驱动程序在加载时,会注册自己作为具有特定名称的文件系统类型的驱动程序。例如,msdos驱动程序注册自己作为名为msdos的文件系统类型的驱动程序。(LKM作者通常将LKM命名为它将驱动的文件系统类型)。


5.3. 智能加载 LKM - Modprobe

一旦您使用 insmodrmmod 掌握了模块的加载和卸载,您就可以使用更高级别的程序 modprobe 让系统为您完成更多工作。有关详细信息,请参阅 modprobe 手册页。

modprobe 主要做的是自动加载您请求的 LKM 的先决条件。它借助您使用 depmod 创建并保存在系统上的文件来实现这一点。

示例

modprobe msdos

这会执行 insmodmsdos.o,但在那之前会执行 insmodfat.o,因为您必须先加载fat.o才能加载msdos.o.

modprobe 为您做的另一件主要事情是,仅给出 LKM 的名称即可找到包含 LKM 的目标模块。例如,modprobe msdos 可能会加载/lib/2.4.2-2/fs/msdos.o。实际上,modprobe 的参数可能是一个完全符号化的名称,您已将其与某个实际模块关联。例如,modprobe eth0 加载适当的网络设备驱动程序以创建和驱动您的eth0设备,前提是您已在modules.conf中正确设置。查看 modprobe 的手册页和配置文件modules.conf(通常是/etc/modules.conf),以获取有关 modprobe 使用的搜索规则的详细信息。

modprobe 尤其重要,因为它默认是内核模块加载程序用来按需加载 LKM 的程序。因此,如果您使用自动模块加载,您需要设置modules.conf,否则事情将无法正常工作。请参阅 第 5.4 节

depmod 扫描您的 LKM 目标文件(通常是所有.o文件在适当的/lib/modules子目录中),并确定哪些 LKM 需要(引用符号)其他 LKM。它生成一个依赖关系文件(通常命名为modules.dep),您通常将其保存在/lib/modules中供 modprobe 使用。

您也可以使用 modprobe 删除 LKM 堆栈。

通过 LKM 配置文件(通常是/etc/modules.conf),您可以微调依赖关系并执行其他高级操作来控制 LKM 的选择。您可以指定在插入和删除 LKM 时运行的程序,例如,初始化设备驱动程序。

如果您维护一个系统并且内存不短缺,那么最好避免 modprobe 及其需要的各种文件和目录,只需在启动脚本中执行原始的 insmod 即可。


5.4. 自动 LKM 加载和卸载

5.4.1. 自动加载

您可以使 LKM 在内核首次需要它时自动加载。您可以使用内核模块加载程序(它是 Linux 内核的一部分)或其旧版本kerneld守护进程。

举例来说,假设您运行一个程序,该程序为 MS-DOS 文件系统中的文件执行 open 系统调用。但是您没有 MS-DOS 文件系统的文件系统驱动程序,既没有绑定到您的基础内核中,也没有作为 LKM 加载。因此,内核不知道如何访问您在磁盘上打开的文件。

内核识别出它没有 MS-DOS 的文件系统驱动程序,但是两种自动模块加载工具中的一种可用,并使用它来导致 LKM 被加载。然后,内核继续执行 open 操作。

在大多数现代系统中,自动内核模块加载的复杂性实际上并不值得。在内存非常小的系统中,这可能是有意义的,因为您可以仅在需要时才将内核的某些部分保存在内存中。但是,这些模块使用的内存量在今天非常便宜,因此通常最好通过启动脚本加载您可能需要的所有模块并将它们保持加载状态。

Red Hat Linux 通过内核模块加载程序使用自动模块加载。

内核模块加载程序和kerneld都使用 modprobe,即 insmod 来插入 LKM。请参阅 第 5.3 节


5.4.1.1. 内核模块加载程序

有关内核模块加载程序的一些文档位于 Linux 2.4 源代码树中的文件Documentation/kmod.txt中。本节比该文件更完整和准确。您也可以在kernel/kmod.c.

中查看其源代码。内核模块加载程序是 Linux 内核的可选部分。如果您在构建时配置内核时选择了 CONFIG_KMOD 功能,您就可以获得它。

当具有内核模块加载程序的内核需要 LKM 时,它会创建一个用户进程(尽管由超级用户拥有),该进程执行 modprobe 以加载 LKM,然后退出。默认情况下,它将 modprobe 查找为/sbin/modprobe,但您可以通过将其文件名写入/proc/sys/kernel/modprobe来设置任何您喜欢的程序作为 modprobe。例如

# echo "sbin/mymodprobe" >/proc/sys/kernel/modprobe

内核模块加载程序将以下参数传递给 modprobe:参数零是 modprobe 的完整文件名。常规参数是-s, -k,以及内核想要的 LKM 的名称。-s是用户不友好的形式--syslog; -k是说--autoclean的隐秘方式。即,来自 modprobe 的消息将发送到 syslog,并且加载的 LKM 将设置“autoclean”标志。

modprobe 调用中最重要的部分当然是模块名称。请注意,modprobe 的“模块名称”参数不一定是实际的模块名称。它通常是表示该模块所扮演的角色的符号名称,您可以使用alias语句在modules.conf中告诉加载哪个 LKM。例如,如果您的以太网适配器需要3c59xLKM,您可能需要以下行

alias eth0 3c59x
/etc/modules.conf中。以下是内核模块加载程序在一些更常见的情况下用于模块名称的内容(内核大约有 20 种情况会调用内核模块加载程序来加载模块):

  • 当您尝试访问设备并且没有设备驱动程序注册以服务该设备的主设备号时,内核会请求名为block-major-Nchar-major-N的模块,其中N是以十进制表示的主设备号,没有前导零。

  • 当您尝试访问网络接口(可能是通过针对它运行 ifconfig)并且没有网络设备驱动程序注册以按该名称服务接口时,内核会请求以与接口名称相同的模块(例如eth0)。 这同样适用于非物理接口的驱动程序,例如ppp0等。

  • 当您尝试访问某个协议族中的套接字,而没有协议驱动程序注册来驱动它时,内核会请求名为net-pf-N的模块,其中N是协议族的编号(十进制,不带前导零)。

  • 当您尝试通过 NFS 系统调用导出目录或以其他方式访问 NFS 服务器时,内核会请求名为nfsd.

  • 的模块。ATA 设备驱动程序(名为ide)通过名称加载相关类别的 ATA 设备驱动程序:ide-disk, ide-cd, ide-floppy, ide-tapeide-scsi.

内核模块加载器使用以下环境变量运行 modprobe(仅限):HOME=/; TERM=linux; PATH=/sbin:/usr/sbin:/bin:/usr/bin.

内核模块加载器是 Linux 2.2 中的新增功能,旨在取代kerneld。 但是,它并不具备kerneld.

的所有功能。在 Linux 2.2 中,内核模块加载器直接创建上述进程。在 Linux 2.4 中,内核模块加载器将模块加载工作提交给 Keventd,它作为 Keventd 的子进程运行。

内核模块加载器是一种非常奇怪的东西。 它违反了 Unix 程序员通常理解的分层,因此不够灵活,难以理解且不够健壮。 许多系统设计者仅仅因为它硬编码了 PATH 就会感到恼火。 您可能更喜欢使用kerneld,或者根本不使用 LKM 的自动加载。


5.4.1.2. Kerneld

kerneld在 Kerneld mini-HOWTO 中有详细解释,可从 Linux 文档项目获取。

kerneld是一个用户进程,它从 modutils 包中运行 kerneld 程序。kerneld与内核建立 IPC 消息通道。 当内核需要 LKM 时,它会在该通道上向kerneld发送消息,然后kerneld运行 modprobe 加载 LKM,然后发回消息给内核,说明已完成。


5.4.2. 自动卸载 - Autoclean

5.4.2.1. Autoclean 标志

每个加载的 LKM 都有一个 autoclean 标志,可以设置或取消设置。您可以使用init_module系统调用的参数来控制此标志。 假设您通过 insmod 执行此操作,则使用--autoclean选项。

您可以在/proc/modules中查看 autoclean 标志的状态。 任何设置了该标志的 LKM 旁边都有autoclean的图例。


5.4.2.2. 删除 Autoclean LKM

autoclean 标志的目的是让您自动删除一段时间内未使用的 LKM(通常为 1 分钟)。 因此,通过使用自动模块加载和卸载,您可以仅保留当前需要的部分内核,并节省内存。

这不如以前重要了,因为内存现在便宜得多。 如果您不需要节省内存,则不必理会模块加载器进程的复杂性。 只需通过初始化脚本加载您可能需要的所有内容,并保持加载状态。

有一个delete_module系统调用的形式表示“删除所有设置了 autoclean 标志且一段时间内未使用的 LKM。” Kerneld 通常每分钟调用一次此调用。 您可以使用 rmmod --all 命令显式调用它。

由于内核模块加载器不执行任何 LKM 的删除操作,因此如果您使用它,您可能希望有一个 cron 作业定期执行 rmmod --all


5.5. /proc/modules

要查看当前加载的 LKM,请执行

cat /proc/modules

您会看到类似这样的行

serial                   24484   0

左列是 LKM 的名称,通常是从中加载它的对象文件的名称,减去“.o”后缀。 但是,您可以使用 insmod 上的一个选项选择您喜欢的任何名称。

“24484”是 LKM 在内存中的大小(以字节为单位)。

“0”是使用计数。 它表示当前有多少事物依赖于 LKM 的加载。 典型的“事物”是打开的设备或挂载的文件系统。 这很重要,因为除非使用计数为零,否则您无法删除 LKM。 LKM 本身会维护此计数,但模块管理器会使用它来决定是否允许卸载。

上述使用计数的描述有一个例外。 您可能会在使用计数列中看到 -1。 这意味着此 LKM 不使用使用计数来确定何时可以卸载。 相反,LKM 注册了一个子例程,模块管理器可以调用该子例程,该子例程将返回一个指示是否可以卸载 LKM 的指示。 在这种情况下,LKM 应该为您提供一些自定义接口和一些文档,以确定何时可以自由卸载 LKM。

不要将使用计数与“依赖关系”混淆,后者将在下面介绍。

这是另一个示例,其中包含更多信息

lp                      5280   0 (unused)
parport_pc              7552   1
parport                 7600   1 [lp parport_pc]
方括号中的内容(“[lp parport_pc]”)描述了依赖关系。 在这里,模块lp发送消息,然后parport_pc都引用模块parport中的地址(通过parport导出的外部符号)。 所以lp发送消息,然后parport_pc“依赖于”(并且是“的依赖项”)parport.

您无法卸载具有依赖关系的 LKM。 但是,您可以通过卸载依赖的 LKM 来删除这些依赖关系。

“(unused)”图例表示 LKM 从未使用过,即它从未处于无法卸载的状态。 内核跟踪此信息的原因很简单:协助自动 LKM 卸载策略。 在自动加载和卸载 LKM 的系统中(请参阅第 5.4 节),您不希望自动加载 LKM,然后在需要加载 LKM 的人有机会使用它之前,因为它未使用而将其卸载。

这是您通常不会看到的东西

mydriver                8154   0 (deleted)
这是一个处于“已删除”状态的 LKM。 这有点用词不当 - 它的意思是 LKM 正在卸载过程中。 您不能再加载依赖于它的 LKM,但它仍然存在于系统中。 卸载 LKM 通常接近瞬时,因此如果您看到此状态,则可能有一个损坏的 LKM。 它的清理例程可能进入了无限循环或停滞,或者崩溃了(导致内核 oops)。 如果是这种情况,则清除此状态的唯一方法是重新启动。

存在类似的状态“正在初始化”和“未初始化”。

图例“(autoclean)”指的是 autoclean 标志,在 第 5.4 节中讨论。


5.6. 我的系统上 LKM 文件位于何处?

LKM 世界足够灵活,您需要加载的文件几乎可以位于系统上的任何位置,但大多数系统都遵循一个约定:LKM .o 文件位于/lib/modules目录中,分为子目录。 每个内核版本都有一个子目录,因为 LKM 特定于内核(请参阅第 6 节)。 每个子目录都包含一组完整的 LKM。

子目录名称是您从 uname --release 命令中获得的值,例如2.2.19第 6.3 节介绍了如何控制该值。

当您构建 Linux 时,标准的 make modulesmake modules_install 应该将作为 Linux 一部分的所有 LKM 安装到正确的发布子目录中。

如果您构建了大量内核,则另一种组织可能更有帮助:将 LKM 与基本内核和其他内核相关文件一起保存在 /boot 的子目录中。 唯一的缺点是您不能让 /boot 驻留在很小的磁盘分区上。 在某些系统中,/boot 位于一个特殊的微型“启动分区”上,并且仅包含足够的文件,以便系统启动到可以挂载其他文件系统的程度。


6. 未解析的符号

加载 LKM 时最常见且最令人沮丧的失败是一堆关于未解析符号的错误消息,如下所示

  msdos.o: unresolved symbol fat_date_unix2dos
  msdos.o: unresolved symbol fat_add_cluster1
  msdos.o: unresolved symbol fat_put_super
  ...
实际上,有许多不同的问题会导致此症状。 无论如何,您可以通过查看/proc/ksyms并确认消息中的符号确实不在列表中来更接近问题。


6.1. 某些 LKM 预先要求其他 LKM

您得到此错误的原因之一是您尚未加载另一个包含 LKM 需要访问的指令或数据的 LKM。 modprobe 的主要目的是避免此失败。 请参阅第 5.3 节


6.2. LKM 必须与基本内核匹配

可加载内核模块的设计者意识到将内核放在多个文件中可能会出现问题,这些文件可能会彼此独立地分发。 如果 LKMmydriver.o被编写和编译为与 Linux 1.2.1 基本内核一起使用,然后有人尝试将其加载到 Linux 1.2.2 内核中怎么办? 如果 1.2.1 和 1.2.2 之间以mydriver.o调用的内核子例程工作方式发生了变化怎么办? 这些是内部内核子例程,因此有什么可以阻止它们从一个版本更改到下一个版本? 您最终可能会得到一个损坏的内核。

为了解决这个问题,LKM 的创建者赋予它们一个内核版本号。 在此示例中,.modinfo的特殊mydriver.o对象文件部分包含“1.2.1”,因为它使用 Linux 1.2.1 中的头文件进行编译。 尝试将其加载到 1.2.2 内核中,insmod 会注意到不匹配并失败,告诉您您有一个内核版本不匹配。

但是等等。 Linux 1.2.1 和 1.2.2 之间真正存在不兼容性且会影响mydriver.o? mydriver.o的几率是多少?它仅调用几个子例程并访问几个数据结构。 我们是否必须根据要插入的特定内核的头文件重新编译每个 LKM?

为了减轻这种负担,insmod 有一个-f选项,该选项“强制”insmod 忽略内核版本不匹配并插入模块。 因为任何两个内核版本之间存在显着差异的情况非常罕见,所以我建议您始终使用-f。 但是,您仍然会收到一条关于不匹配的警告消息。 无法关闭该消息。

但是 LKM 设计者仍然希望解决偶尔发生的不兼容更改问题。 因此,他们发明了一种非常聪明的方法,可以使 LKM 插入过程对 LKM 使用的每个内核子例程的实际内容敏感。 它被称为符号版本控制(有时不太清楚地称为“模块版本控制”)。 它是可选的,您可以通过“CONFIG_MODVERSIONS”内核配置选项在配置内核时选择它。

当您使用符号版本控制构建基本内核或 LKM 时,为 LKM 使用导出的各种符号被定义为宏。 宏的定义是相同的符号名称加上符号命名子例程的参数和返回值类型的十六进制哈希值(基于程序 genksyms 对子例程源代码的分析)。 因此,让我们看一下register_chrdev子例程。register_chrdev是基本内核中的一个子例程,设备驱动程序 LKM 经常调用它。 使用符号版本控制时,存在一个 C 宏定义,例如

  #define register_chrdev register_chrdev_Rc8dc8350

此宏定义在 C 源文件中有效,该文件定义register_chrdev以及任何引用register_chrdev,因此,虽然你的眼睛看到的是register_chrdev当你阅读代码时,C 预处理器知道该函数实际上被调用为register_chrdev_Rc8dc8350.

这个垃圾后缀是什么意思?它是以下内容的参数和返回值的类型哈希:register_chrdev。参数和返回值类型的任何两种组合都具有相同的哈希值。

假设有人在register_chrdevLinux 1.2.1 和 Linux 1.2.2 之间添加了一个参数。在 1.2.1 中,register_chrdevregister_chrdev_Rc8dc8350的宏,但在 1.2.2 中,它是register_chrdev_R12f8dc01的宏。在mydriver.o中,使用 Linux 1.2.1 头文件编译后,存在对register_chrdev_Rc8dc8350的外部引用,但 1.2.2 基本内核没有导出此类符号。相反,1.2.2 基本内核导出一个符号register_chrdev_R12f8dc01.

因此,如果您尝试将此 1.2.1mydriver.o插入到此 1.2.2 基本内核中,您将会失败。并且错误消息不是关于内核版本不匹配,而是简单的“未解析的符号引用”。

尽管这很聪明,但有时实际上会适得其反。 genksyms 的工作方式是,它通常会为本质上相同的参数列表生成不同的哈希值。

并且符号版本控制甚至不能保证兼容性。它只捕获了函数定义中一小部分可能使其不向后兼容的更改。如果register_chrdev解释其一个参数的方式发生了不向后兼容的更改,则其版本后缀不会更改 -- 参数仍然具有相同的 C 类型。

并且像-f这样的 insmod 选项也无法解决此问题。

因此,通常不建议使用符号版本控制。

当然,如果您的基本内核是使用符号版本控制编译的,那么您必须同样编译所有 LKM,反之亦然。否则,您肯定会收到那些“未解析的符号引用”错误。


6.3. 如果您运行多个内核

既然我们已经了解了您通常为不同的基本内核拥有不同版本的 LKM,那么问题就出现了,对于具有多个内核版本的系统(即您可以在启动时选择内核)应该怎么做。您要确保为内核 A 构建的 LKM 在您启动内核 A 时被插入,而为内核 B 构建的 LKM 在您启动内核 B 时被插入。

特别是,每当您升级内核时,如果您很聪明,您会将新内核和旧内核都保留在系统上,直到您确定新内核可以工作为止。

最常见的方法是使用 modprobe 的 LKM 搜索功能。modprobe 了解 第 5.6 节中描述的常规 LKM 文件组织,并根据正在运行的内核从相应的子目录加载 LKM。

您可以通过在构建内核时编辑主内核 Makefile 并在顶部设置 VERSION、PATCHLEVEL、SUBLEVEL 和 EXTRAVERSION 变量来设置 uname --release 值,该值是 modprobe 查找的子目录的名称。


6.4. SMP 符号

除了上面提到的校验和之外,如果符号是在为对称多处理 (SMP) 机器构建的代码中定义或引用,则符号版本前缀包含“smp”。这意味着它是为可能具有多个 CPU 的系统构建的。您可以通过 Linux 内核配置过程(make config 等)选择是否构建 SMP 功能,即使用 CONFIG_SMP 配置选项。

因此,如果您使用符号版本控制,如果基本内核是在具有 SMP 功能的情况下构建的,而您要插入的 LKM 不是,或者反之亦然,您将收到未解析的符号。

如果您不使用符号版本控制,请不用介意。

请注意,通常没有理由从内核中省略 SMP 功能,即使您只有一个 CPU。仅仅因为存在该功能并不意味着您必须拥有多个 CPU。但是,在某些机器上,支持 SMP 的内核将无法启动,因为它得出结论,有零个 CPU!


6.5. 您未获得访问该符号的许可

一些内核代码的版权所有者将其程序许可给公众进行复制和使用,但仅以受限制的方式进行。例如,许可证可能说您只能从同样获得公众许可的程序调用您的程序副本。

(这是否令人困惑?这里有一个例子:Bob 编写了一个 LKM,为其他 LKM 提供数据压缩子程序。他根据 GNU 公共许可证 (GPL) 将他的程序许可给公众。根据某些解释,该许可证表示,如果您制作 Bob 的 LKM 的副本,如果 Mary 不向世界提供她的源代码,您就不能允许 Mary 的 LKM 调用它的压缩子程序。目的是鼓励 Mary 公开她的源代码)。

为了支持和强制执行此类许可证,许可人可以导致他的程序以特殊名称导出符号,该名称是符号的真实名称加上前缀“GPLONLY”。客户端 LKM 的一个天真的加载器将无法解析这些符号。示例:Bob 的 LKM 提供服务 bobsService() 并声明它是一个 GPL 符号。因此,LKM 以名称 GPLONLY_bobsService 导出 bobsService()。如果 Mary 的 LKM 引用 bobsService,天真的加载器将无法找到它,因此将无法加载 Mary 的 LKM。

但是,现代版本的 insmod 知道在找不到 bobsService 时检查 GPLONLY_bobsService。但是,除非 Mary 的 LKM 声明它已获得 GPL 下的公众许可,否则现代 insmod 将拒绝这样做。

这样做的目的似乎是为了防止任何人意外地违反许可证(或者可信地声称他意外地违反了许可证)。如果您想这样做,并不难规避限制。

如果您看到此失败,可能是因为您使用的是不了解 GPLONLY 的旧加载器 (insmode)。

唯一其他原因是 LKM 作者编写源代码的方式使其永远无法加载到任何 Linux 内核中,因此作者分发它没有意义。


6.6. LKM 必须匹配前提 LKM

LKM 必须与基本内核兼容的方式相同,它必须与它访问的任何 LKM 兼容(例如,第一个 LKM 调用第二个 LKM 中的一个子程序)。前面的章节将他们的讨论限制为基本内核,只是为了保持简单。


7. 如何在没有磁盘设备驱动程序的情况下启动

对于大多数系统,ATA 磁盘设备驱动程序必须绑定到基本内核中,因为根文件系统位于 ATA 磁盘上 [2],并且内核无法挂载根文件系统,更不用说从中读取任何 LKM,而没有 ATA 磁盘驱动程序。但是,如果您真的希望您的根文件系统的设备驱动程序是一个 LKM,那么这里是如何使用 Initrd 来完成的

“Initrd”是 Linux 的“初始 ramdisk”功能的名称。有了这个,您让您的加载器(可能是 LILO 或 Grub)在启动内核之前将文件系统加载到内存中(作为 ramdisk)。当它启动内核时,它会告诉它将 ramdisk 挂载为根文件系统。您将真实根文件系统的磁盘设备驱动程序和加载它所需的所有软件都放在该 ramdisk 文件系统中。您的启动程序(位于 ramdisk 中)最终会将真实(磁盘)文件系统挂载为根文件系统。请注意,ramdisk 不需要任何设备驱动程序。

但是,这并没有让您免于必须绑定到基本内核 1) ramdisk 中的文件系统的文件系统驱动程序,以及 2) ramdisk 中程序的可执行解释器。


8. 关于模块参数

比较传递给 LKM 的参数和传递给绑定到基本内核中的模块的参数很有用,特别是考虑到模块通常可以以任何一种方式运行。

我们已经在上面看到,您可以通过指定类似io=0x300insmod 命令将参数传递给 LKM。对于绑定到基本内核中的模块,您通过内核启动参数将参数传递给它。指定内核启动参数的一种常见方法是在 lilo 启动提示符下。另一种方法是使用append中的 lilo 配置文件中的语句。

内核在您加载 LKM 时对其进行初始化。它在启动时初始化一个绑定模块。

由于只有一个内核启动参数字符串,因此您需要某种方式在该字符串中识别哪些参数传递给哪些模块。这样做的规则是,如果有一个名为xyz的模块,那么一个名为xyz的内核启动参数是针对该模块的。内核启动参数的值是一个任意字符串,只有该模块才有意义。

这就是为什么您有时会看到一个 LKM,其唯一的参数是它自己的名称。例如,您使用如下命令加载 Mitsumi CDROM 驱动程序

  insmod mcd mcd=0x340
拥有名为mcd的参数而不是,例如,io似乎很荒谬,但这样做是为了与您绑定mcd到基本内核的情况保持一致,在这种情况下,您将使用字符mcd=0x340在内核启动参数中选择 I/O 端口地址。


9. 持久数据

一些 LKM 设置为保留从一个加载到下一个加载的信息。这称为持久数据。当您使用 rmmod 删除其中一个 LKM 时,rmmod 会从 LKM 的工作存储中提取某些值并将它们存储在一个文件中。当您下次使用 insmod 插入 LKM 时,insmod 会从该文件中读取持久数据并将其插入到 LKM 中。

请参阅 insmodrmmod 上的--persist选项。

持久数据是在 2000 年 11 月引入的。


10. 技术细节

10.1. 它们如何工作

insmod 进行init_module系统调用以将 LKM 加载到内核内存中。加载它是容易的部分,但是,内核如何知道使用它?答案是,init_module系统调用会在加载 LKM 后立即调用 LKM 的初始化例程。insmod 传递给init_moduleLKM 中名为init_module的子程序的地址作为其初始化例程。

(这令人困惑 -- 每个 LKM 都有一个名为init_module的子程序,并且基本内核具有一个同名的系统调用,该调用可以通过标准 C 库中也名为init_module).

的子程序访问。LKM 作者设置了init_module来调用一个内核函数,该函数注册 LKM 包含的子程序。例如,字符设备驱动程序的init_module子程序可能会调用内核的register_chrdev子程序,传递它打算驱动的设备的主号和次号以及它自己的“open”例程的地址等参数。register_chrdev在基本内核表中记录,当内核想要打开该特定设备时,它应该调用我们 LKM 中的 open 例程。

但是,精明的读者现在会问 LKM 的init_module子程序是如何知道基本内核的register_chrdev子程序的地址的。这不是一个系统调用,而是绑定到基本内核中的一个普通子程序。调用它意味着分支到它的地址。那么我们的 LKM,它不是在基本内核附近编译的,如何知道该地址?这个问题的答案是在 insmod 时发生的重定位。

在 Linux 2.4 和 Linux 2.6 之间,重定位的发生方式根本不同。在 2.6 中,insmod 几乎只是将 LKM 文件(.ko 文件)的逐字内容传递给内核,内核进行重定位。在 2.4 中,insmod 进行重定位并将完全链接的模块映像传递给内核,准备将其填充到内核内存中。下面的描述涵盖了 2.4 的情况。

insmod 作为一个重定位链接器/加载器。LKM 对象文件包含对符号register_chrdev. insmod 执行一个query_module系统调用,以查找现有内核导出的各种符号的地址。register_chrdev也在其中。query_module返回register_chrdev的地址,并且 insmod 将其修补到LKM中,其中LKM引用register_chrdev.

如果你想看到 insmod 可以从query_module系统调用中获取的信息类型,请查看/proc/ksyms.

请注意,一些LKM调用其他LKM中的子程序。 它们可以这样做是因为LKM对象文件中的__ksymtab发送消息,然后.kstrtab节。 这些节一起列出了LKM对象文件中的外部符号,这些符号应该可以被将来插入的其他LKM访问。 insmod 查看__ksymtab发送消息,然后.kstrtab并告诉内核将这些符号添加到其导出的内核符号表中。

要亲自查看这一点,请插入LKMmsdos.o然后注意在/proc/ksyms中的符号fat_add_cluster(它是fat.oLKM中的子程序的名称)。 任何后续插入的LKM都可以分支到fat_add_cluster,事实上msdos.o就是这样做的。


10.2. .modinfo 节

ELF对象文件由各种命名节组成。 其中一些是对象文件的基本部分,例如.text节包含加载程序加载的可执行代码。 但是你可以创建任何你想要的节,并让特殊的程序使用它。 对于Linux LKM,存在.modinfo节。 LKM不一定需要名为.modinfo的节才能工作,但是你应该用来编写LKM的代码的宏会导致生成一个节,因此它们通常这样做。

要查看对象文件的节,包括.modinfo节(如果存在),请使用 objdump 程序。 例如

要查看msdos LKM的对象文件中的所有节

objdump msdos.o --section-headers
要查看.modinfo节的内容
objdump msdos.o --full-contents --section=.modinfo

你可以使用 modinfo 程序来解释.modinfo节的内容。

那么.modinfo节中有什么?谁使用它? insmod.modinfo节用于以下目的:

  • 它包含构建模块的内核发布版本号。 也就是,编译模块时使用的内核源代码树的头文件。

    insmod 使用该信息,如第 6 节中所述。

  • 它描述了LKM的参数形式。 insmod 使用此信息将你在 insmod 命令行上提供的参数格式化为数据结构初始值,insmod 在加载LKM时将其插入到LKM中。


10.3. __ksymtab 和 .kstrtab 节

在LKM对象文件中经常找到的另外两个节命名为__ksymtab发送消息,然后.kstrtab。 它们一起列出了LKM中应该可访问(导出)到内核其他部分的符号。 符号只是LKM中地址的文本名称。 LKM A的对象文件可以通过名称引用LKM B中的地址(例如,getBinfo”)。 当你插入LKM A时,在插入LKM B之后,insmod 可以将LKM B中名为getBinfo的数据/子程序的实际地址插入到LKM A中。

有关符号绑定的更多令人头痛的细节,请参阅第 10.1 节


10.4. Ksymoops 符号

insmod 在加载LKM时向其添加了一堆导出的符号。 这些符号都旨在帮助 ksymoops 完成其工作。 ksymoops 是一个解释和显示“oops”的程序。 “oops”显示是Linux内核检测到内部内核错误(并因此终止进程)时显示的内容。 此信息包含内核中的一堆地址,以十六进制显示。

ksymoops 查看十六进制地址,在内核符号表中查找它们(你可以在/proc/ksyms(Linux 2.4)或/proc/kallsyms(Linux 2.6)中看到),并将oops消息中的地址转换为符号地址,你可以在汇编程序列表中查找这些地址。

因此,假设你的LKM崩溃了。 oops消息包含导致错误的指令的地址,并且你希望 ksymoops 告诉你的是:1)该指令在哪个LKM中,以及 2)该指令相对于该LKM的汇编程序列表在哪里? 对于oops消息中的数据地址,也会出现类似的问题。

要回答这些问题,ksymoops 必须能够从内核符号表中获取LKM的各个节的加载点和长度。

好吧,在Linux 2.4中,insmod 知道这些地址,因此它只是为它们创建符号,并将它们包含在它与LKM一起加载的符号中。

特别是,这些符号被命名为(你可以通过查看/proc/ksyms):

__insmod_name_Ssectionname_Llength

name是LKM名称(正如你在/proc/modules.

sectionname中看到的那样),是节名称,例如.text(不要忘记前导句点)。

length是节的长度,以十进制表示。

当然,符号的值是节的地址。

Insmod 还添加了一个非常有用的符号,它告诉我们LKM是从哪个文件加载的。 该符号的名称为

__insmod_name_Ofilespec_Mmtime_Vversion

name是LKM名称,如上所述。

filespec是用于标识包含LKM的文件的文件规范。 请注意,它不一定仍以该名称存在,并且可能有多个文件规范可以用来引用同一个文件。 例如,../dir1/mylkm.o发送消息,然后/lib/dir1/mylkm.o.

mtime是该文件的修改时间,以标准的Unix表示形式(自 1969 年以来的秒数),以十六进制表示。

version告诉构建LKM的内核版本级别(与.modinfo节中相同)。 它是宏LINUX_VERSION_CODE在Linux的linux/version.h文件中的值。 例如,132101.

此符号的值没有意义。

在Linux 2.6中,它的工作方式不同。 (我还没有弄清楚如何工作)。


10.5. 其他符号

insmod 添加了另一个类似于 ksymoops 符号的符号。 这个符号告诉我们持久性数据在LKM中的位置,rmmod 需要知道该信息才能保存持久性数据。

__insmod_name_Plength


10.6. 调试符号

还有另一种与 LKM 相关的符号:kallsyms 符号。 这些不是导出的符号; 它们不会出现在proc/ksyms中。 它们指的是内核中的地址,除了它们所在的模块之外,与任何人都无关,并且不应被调试器以外的任何东西引用。 Kdb,Linux内核自带的内核调试器,是 kallsyms 符号的用户之一。

kallsyms 工具适用于基本内核和 LKM。 对于基本内核,你可以在构建基本内核时选择它,使用 CONFIG_KALLSYMS 配置选项。 完成后,内核将包含基本内核对象文件中所有符号的 kallsyms 符号。 如果你看到符号__start___kallsyms/proc/ksyms.

,你就知道你的基本内核正在参与 kallsyms 工具。init_module对于 LKM,你可以在加载时决定它是否包含 kallsyms 符号。 你将 kallsyms 定义包含在传递给的系统调用的数据中,以加载 LKM。 如果 1) 你指定--kallsyms/proc/ksyms选项,或者 2) insmod 通过查看

确定基本内核正在参与 kallsyms 工具,insmod 就会这样做。 insmod 定义的 kallsyms 是 LKM 对象文件中的所有符号。 也就是说,这些是你在 LKM 对象文件上运行 nm 时看到的符号。

每个参与 kallsyms 的加载的 LKM 都有自己的 kallsyms 符号表。 当基本内核参与 kallsyms 工具时,各个 LKM kallysms 符号表链接到主符号表中,以便调试器可以在内核中的任何位置查找符号。 当基本内核未参与 kallsyms 时,调试器必须显式地查看特定的 LKM 才能查找该 LKM 的符号。 例如,Kdb 无法做到这一点。 因此,基本规则是:如果你要进行任何内核调试,请使用 CONFIG_KALLSYMS。请注意,__kallsyms

节与 LKM 无关。 这是基本内核对象模块中的一个节。 基本内核没有像 insmod 这样高级的工具来加载它,因此它需要额外的对象文件节来促进其参与 kallsyms。请注意,节的内容。

同样,程序 kallsyms 与 LKM 无关。 它是创建还有另一种调试符号——gcc 使用其-g


选项创建的符号。 这些与 kallsyms 工具无关。 它们不会加载到内核内存中。 Kdb 不使用它们。 但是 Kgdb(从内核内存以及源文件和对象文件中获取信息)会使用它们。

10.7. 加载的内存分配

本节介绍 Linux 如何分配内存来加载 LKM。 它不是关于 LKM 如何动态分配内存,这与内核的任何其他部分相同。

LKM 所在的内存与基本内核所在的内存略有不同。 基本内核始终加载到实际内存的一个大的连续区域中,其实际地址等于其虚拟地址。 这是可能的,因为基本内核是第一个加载的东西(除了加载程序之外)——它有一个完全开放的空闲空间可以加载。 并且由于 Linux 内核不可分页,因此它会永远留在其家园中。当你加载 LKM 时,实际内存已经全部碎片化——你不能简单地将 LKM 添加到基本内核的末尾。 但是 LKM 需要位于连续的虚拟内存中,因此 Linux 使用vmalloc

来分配虚拟内存的连续区域(在内核地址空间中),该区域在实际内存中可能不连续。 但是*内存仍然不可分页*。 LKM 从一开始就加载到实际页面帧中,并一直保留在这些实际页面帧中直到卸载。

此设计基于以下原则:获得大的连续虚拟内存区域比获得大的连续实际内存区域容易得多,因为虚拟地址空间比实际内存大几个数量级。 在虚拟内存的早期,这当然是正确的——一台 32 位机器拥有 4GiB 的虚拟地址空间,而实际内存很少超过 64 MiB。 然而,现在情况往往恰恰相反,虚拟地址空间成为受限的资源。 因此,这种 LKM 加载策略可能在你的系统上没有意义。

某些 CPU 可以利用基本内核的属性来更快地访问基本内核内存。 例如,在一台机器上,整个基本内核由一个页表条目覆盖,因此由转换旁路缓冲区 (TLB) 中的一个条目覆盖。 自然,该 TLB 条目几乎总是存在的。 对于此机器上的 LKM,LKM 加载到的每个内存页面都有一个页表条目。 更常见的是,当 CPU 去访问页面时,页面的条目不在 TLB 中,这意味着访问速度较慢。

据说 PowerPC Linux 对其地址转换进行了一些处理,导致在访问基本内核内存和访问 LKM 内存之间切换的成本很高。我对这方面的情况了解不多。

基本内核在其宝贵的连续域中包含大量可重用内存 -- kmalloc 池。在某些 Linux 版本中,模块加载器首先尝试从该池中获取连续内存,以加载 LKM,只有在没有足够大的空间时,才会转到 vmalloc 空间。Andi Kleen 在 2002 年 10 月向 Linux 2.5 提交了执行此操作的代码。他声称这种差异在几个百分点的范围内。


10.8. Linux 内部机制

如果您对 Linux 内核关于 LKM 的内部运作感兴趣,本节可以帮助您入门。您无需了解任何这些内容即可开发、构建和使用 LKM。

处理 LKM 的代码位于源文件中kernel/module.c位于 Linux 源代码树中。

内核模块加载器(参见第 5.4 节)位于kernel/kmod.c.

(好吧,这并不是一个好的开始,但至少我这里有一个框架,可以在将来添加这些信息)。


11. 编写您自己的可加载内核模块

Peter J Salzman、Michael Burian 和 Ori Pomerantz 撰写的 Linux 内核模块编程指南 对编写您自己的 LKM 进行了完整的解释。本书也有印刷版。它有两个版本:一个用于 Linux 2.4,另一个用于 2.6。

曾经,Linux 2.4 版本的文档相当过时,并且包含一两个错误。

以下是关于编写 LKM 的一些事项,至少曾经不在其中。如果它仍然正确,请告知 LKM HOWTO 的作者。如果不是,他可以从 LKM HOWTO 中删除此部分。


11.1. 更简单的 hello.c

Lkmpg 给出了世界上最简单的 LKM 的示例,hello-1.c。但它并不像它可能的那样简单,并且取决于您是否在系统上以某种方式设置了内核消息传递才能看到它工作。最后,该程序要求您包含-D编译命令中的选项才能工作,因为它没有在源代码中定义一些宏,而这些宏定义应该放在源代码中。

这是一个改进后的世界上最简单的 LKM,hello.c.

/* hello.c 
 * 
 * "Hello, world" - the loadable kernel module version. 
 *
 * Compile this with 
 *
 *          gcc -c hello.c -Wall
 */

/* Declare what kind of code we want from the header files */
#define __KERNEL__         /* We're part of the kernel */
#define MODULE             /* Not a permanent part, though. */

/* Standard headers for LKMs */
#include <linux/modversions.h> 
#include <linux/module.h>  

#include <linux/tty.h>      /* console_print() interface */

/* Initialize the LKM */
int init_module()
{
  console_print("Hello, world - this is the kernel speaking\n");
  /* More normal is printk(), but there's less that can go wrong with 
     console_print(), so let's start simple.
  */

  /* If we return a non zero value, it means that 
   * init_module failed and the LKM can't be loaded 
   */
  return 0;
}


/* Cleanup - undo whatever init_module did */
void cleanup_module()
{
  console_print("Short is the life of an LKM\n");
}

使用简单的命令编译它

$ gcc -c -Wall -nostdinc -I /usr/src/linux/include hello.c

The-I以上假设您拥有构建基本内核(您希望加载到的内核的基本内核)的源代码,该源代码位于传统位置,hello.c)。/usr/src/linux。如果您足够自虐地在基本内核中使用符号版本控制,那么您最好也对该内核源代码运行 'make dep',因为这将构建 .ver 文件,这些文件会更改所有符号的名称。

但请注意,不安装内核头文件是相当常见的,并且通常安装的是错误的头文件。当您使用从发行版 CD 加载的内核时,通常必须单独加载其头文件。为了安全起见,如果您正在玩编译 LKM,您真的应该编译自己的内核,这样您就可以确切地知道您正在使用的内容,并且绝对可以确保您正在使用匹配的头文件。

The-nostdinc选项并非绝对必要,但这样做是正确的。它可以避免您陷入困境,并提醒您标准的 C 库的服务(您可能已经在您的脑海中将它与 C 本身融合在一起)不适用于内核代码。-nostdinc表示不要在包含文件搜索路径中包含“标准”目录。这意味着,最值得注意的是,/usr/include.

The-c选项表示您只想创建一个对象 (.o) 文件,而不是 gcc 的默认设置,后者是创建对象文件,然后将其与一些其他标准对象文件链接,以创建适合在用户进程中 exec 的东西。由于您不会 exec 这个模块,而是将其添加到内核中,因此该链接阶段将完全不合适。

-Wall(这使得编译器警告您关于许多种可疑的代码)显然不是必要的,但是这个程序不应该产生任何警告。如果它产生了警告,您需要修复一些东西。


11.2. 使用内核构建系统

Lkmpg 包含构建(编译)LKM 的精细说明(除了 __KERNEL__ 宏和通常的 MODULE 宏应该在源代码中定义,而不是像 Lkmpg 建议的那样使用-D编译器选项)。但值得一提的是,一些 Linux 内核程序员认为构建 LKM 的唯一正确方法是将其添加到完整 Linux 源代码树的副本中,并像 Linux 中的 LKM 一样使用现有的 Linux make 文件来构建它。

这样做有一些优点。最大的优点是,当 Linux 程序员以影响您构建 LKM 的方式更改 LKM 与内核其余部分接口的方式时,您可以涵盖到。

另一方面,从代码管理角度来看,您可能会发现您确实需要将自己的代码和 Linux 分开,并且从编码角度来看,您确实需要了解您的代码是如何编译的所有复杂性,尤其是在它发生变化时。


11.3. Rubini 等人:Linux 设备驱动程序

关于编写设备驱动程序最受欢迎的书籍是 O'Reilly 的 Linux 设备驱动程序,作者是 Alessandro Rubini、Jonathan Corbet 和 Greg Kroah-Hartman。

即使您编写的 LKM 不是设备驱动程序,您也可以从本书中学到很多对您有帮助的东西。

本书的第一版涵盖了 Linux 2.0,并附有关于 2.2 中差异的注释。第二版(2001 年 6 月)涵盖了 Linux 2.4。第三版(2005 年 4 月)涵盖了 Linux 2.6。当然,如果您对 Linux 有任何了解,您就会知道像这样的书并不能完美地涵盖任何版本,因为 Linux 经常发生变化。第三版发布一个月后的 Linux 2.6 与本书编写的 Linux 2.6 存在显着差异。

本书的第二版可在 FDL 下获得。您可以在 http://www.xml.com/ldd/chapter/book/ 阅读它。第三版根据 Creative Commons Attribution-ShareAlike 许可条款提供,您可以在 http://lwn.net/Kernel/LDD3/ 找到它。

本书也可以在任何像样的技术书店购买印刷版。


11.4. 模块使用计数

至关重要的是,内核不要在模块卸载后尝试引用模块的代码;也就是说,您不得在使用模块时卸载它。一个使用中的例子是一个设备特殊文件打开的设备驱动程序。由于它有一个打开的文件描述符,用户可能会对设备执行读取,并且为了执行该读取,内核会想要调用设备驱动程序中的一个函数。您可以看出,如果在读取之前卸载了该设备驱动程序模块,则会出现问题 -- 内核会重用曾经包含读取子程序的内存,并且无法知道内核在认为自己调用读取子程序时会跳转到哪些指令。

在最初的设计中,LKM 会递增和递减其使用计数,以告知模块管理器是否可以卸载它。例如,如果它是一个文件系统驱动程序,它会在有人挂载它驱动的类型的文件系统时递增使用计数,并在卸载时递减它。

后来添加了一种更灵活的替代方案。您的 LKM 可以注册一个函数,模块管理器会在它想知道是否可以卸载模块时调用该函数。如果函数返回一个true值,这意味着 LKM 正忙,无法卸载。如果它返回一个false值,则 LKM 处于空闲状态,可以卸载。模块管理器从调用模块繁忙函数之前到其清理子程序返回或休眠之后一直持有大内核锁,除非您做了一些奇怪的事情,否则这应该意味着您的 LKM 在您报告“不忙”和您清理之间不会变得繁忙。

那么如何注册模块繁忙函数呢?通过将其地址放在不幸命名的can_unload模块描述符(“struct module”)中的字段中。这个名字确实很不幸,因为它返回的布尔值与“can unload”的含义完全相反:如果模块管理器不能卸载 LKM,则为 true。

模块管理器确保它不会在模块的初始化子程序返回或休眠之前尝试卸载模块,因此您可以安全地设置can_unload初始化子程序中除休眠之后以外的任何位置的字段。

can_unload鲜为人知且很少使用。从 Linux 2.6 开始,它不再存在。

无论您使用传统的使用计数can_unload, 在某些情况下,您无法确定您的模块在使用时不会被卸载。如果您的 LKM 创建了一个执行 LKM 代码的内核线程,那么几乎不可能绝对确定该线程在 LKM 被卸载之前已经消失。您可以在 LKM 中提供各种其他内核服务地址,这些地址不会正确地让您知道它们何时被遗忘。

这个问题曾经比现在更严重。例如,过去如果您的 LKM 创建了一个 proc 文件系统文件,您就无法阻止 LKM 在某些进程执行该文件的读取和写入例程时被卸载。这个问题和其他一些实例已经通过让 LKM外部的代码理解它正在使用的地址可能在 LKM 中来解决,因此会根据需要递增和递减使用计数。在这种函数实现的地方,您经常会看到一个名为“owner”的结构成员,它是 LKM 的句柄(即 struct module 地址)。

这些问题可能会在未来的 Linux 版本中得到修复。在此之前,您只能祈祷好运。有些人认为这些类型的问题非常难以修复,以至于 Linux 的正确设计应该是不可能卸载 LKM。从 Linux 2.6 开始,CONFIG_MODULE_UNLOAD 内核构建配置选项决定是否允许模块卸载。


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 的代码用来操作其引用计数的接口已被替换。


13. LKM 的版权注意事项

关于 LKM 的一个长期存在的问题是,考虑到 Linux 内核是在 GPL 下分发的,GPL 的条款是否适用于它。例如,仅以二进制形式发布 LKM 是否可以?本节介绍围绕 LKM 的版权问题,这些问题既有趣又复杂。公平警告:我们没有得出结论。法律尚未确定,并且有很多好的但相互冲突的论点。

请记住,各国都有不同的版权法,因此即使您在一个国家/地区弄清楚了问题的答案,它在另一个国家/地区也可能不同。但版权法实际上非常相似,本节不会详细介绍到足以真正产生影响的程度。

让我们从头开始,看看什么是版权。

主要地,版权是某人阻止其他人复制某物的权利。它是一项法律权利,而不是道德权利。这意味着它是由法律创建的,目的是产生一些实际效果,而不是人们认为人们自然有权获得的东西。

版权试图带来的主要效果是作者因其创造的东西而获得报酬。有些人认为这本身就是一个有效的目标,因为作者对其创造的价值具有自然的权利。但从历史上看,这并不是版权的真正目标。真正的目标是让作者因其作品获得报酬的次要目标:它导致作者首先进行创作。如果作者会因此获得报酬,那么他更有可能花时间和金钱进行写作。

版权法的实际运作只是近似地实现了这一目标。我们都看到过这样的案例:法律被用来以根本无助于实现该目标的方式转移财富。例如,音乐出版商拒绝某人复制一首他反正不会付费的歌曲的许可。立法者认为这是附带损害——版权法为促使作品的创作所做的事情弥补了其他情况下毫无意义的复制限制。

但是,当涉及到 LKM 时,还有另一个更复杂的版权法领域很重要:衍生作品。版权法赋予作者阻止他人创作衍生作品的权利。衍生作品不是作者所写内容的副本。那么它是什么呢?

衍生作品的定义难以捉摸,但这里有一些例子:当您将一本书从英语翻译成法语时,法语版本是英语作品的衍生作品。如果您为小说写了一个新章节,那么您的新章节就是该小说的衍生作品。如果您为哈利波特系列写了一本全新的书,其中包含相同的角色和背景,那么这就是所有哈利波特书籍的衍生作品。如果您在生日贺卡上画了一个您想到的呆伯特漫画,那么这就是所有呆伯特漫画、书籍等的衍生作品。

这使我们想到了 LKM,因为许多人认为 LKM 是 Linux 内核的衍生作品。自由软件基金会已经这么说了。 Linus Torvalds 曾说过有时是的。没有法院对此做出过任何裁决。

现在让我们转向 Linux 的版权。为了便于讨论,当我们说“Linux”时,我们指的是您从 kernel.org 下载的作为常规 Linux 内核的 tarball 的内容。

谁拥有 Linux 的版权?很多人。几乎每个为 Linux 贡献代码的人都保留了自己的版权。其中一些工作是受雇完成的,因此雇佣公司拥有版权。 Linus Torvalds 是最著名的版权所有者,但他拥有 Linux 中非常小的一部分的版权。

这些人如何起诉他们的版权?嗯,没有人与他们达成协议购买复制权。这不切实际。但是,他们都向公众提供版权许可——相同的许可。该许可证已记录并包含在 tarball 的文件中,称为通用公共许可证 (GPL)。 GPL 不是 Linux 特有的。它由自由软件基金会在 Linux 存在之前开发,并且在 Linus 是唯一的版权所有者时被 Linus 简单地选中。并且 Linus 在没有作者提供相同许可的情况下不会将任何代码放入 tarball 中。

版权许可是版权所有者允许您做一些他有权阻止您做的事情,例如制作副本或衍生作品。成为公共许可意味着它提供给公众,而不是版权所有者提供给他认识的特定人员。

GPL 允许您对代码执行几乎任何操作——几乎就像版权所有者放弃了他们所有的版权一样。但并非完全如此:有附加条件。许可证有条件。为了获得许可,您必须满足这些条件。我们在此关心的条件是以下两件事之一,或两者兼而有之,具体取决于您如何阅读许可证文件(该文件含义模糊)。 a) 如果您分发 Linux 的衍生作品,您必须提供整个衍生作品的源代码;或 b) 如果您分发包含 Linux 的作品,您必须提供整个作品的源代码。

现在我们来到了真正的问题:您有什么样的权利来分发您编写的 LKM?

当然,许多人认为您可以按照您喜欢的任何条款分发 LKM,包括仅限二进制文件,而 Linux 版权所有者对此无话可说。您分发的只不过是您自己的代码。而且它不是任何东西的衍生作品。许多人确实分发仅限二进制文件的 LKM,并且认为 LKM 的一个主要好处是能够做到这一点。

其他人则有不同的看法:LKM 虽然是原创作品,但它是 Linux 的衍生作品。 Linux 版权所有者有权控制分发。他们给你的唯一分发许可就是 GPL,并且该许可仅在您提供源代码的条件下才能获得。

让我们更仔细地研究一下 LKM 是否为 Linux 的衍生作品的问题。支持它的论点是,编写 LKM 就像为小说编写补充章节一样。我们知道后者正在创作衍生作品。 LKM 就像章节一样,因为它专门设计为与现有 Linux 内核组成一个整体。它在任何其他上下文中都没有用处,并且在部署时,它与 Linux 的其余部分紧密地交织在一起。您通常使用一堆 Linux 头文件来编译它的事实证明它只是 Linux 的扩展(不要将此与另一个论点混淆——#include 实际上意味着您正在您的对象代码中分发该头文件)。请注意,在运行时加载的内核模块本质上与您选择静态绑定到基本内核的程序相同。如果为 Linux 源代码树编写模块正在创建衍生作品,那么编写 LKM 也必须如此。 LKM 通常必须更新以符合基本内核的更新。

Wasabi Systems 公司销售的内核拥有比 Linux 更宽松的许可。该公司发布了一篇文章,更详细地论证了 LKM 是 Linux 的衍生作品,因此您应该警惕为其发布二进制形式的 LKM。

反对的观点认为,LKM 是与 Linux 交互的东西,而不是 Linux 的一部分。它将 LKM 比作用户空间程序,通过系统调用与内核通信,或者像 FTP 客户端程序(这不会是任何 FTP 服务器程序的衍生作品)。

这个问题也涉及到书籍和计算机程序不具有类比性的领域,因为计算机程序会做某事,而书籍只是向人传达一个想法。加载 LKM 可能更像是将附件插入到您的真空吸尘器中,而不是像将页面插入到您的书中。我们知道,真空吸尘器附件的蓝图不是真空吸尘器蓝图的衍生作品。

这就是我所能解释的了。这里似乎存在一个程度问题,需要由法官来划定界限。

但是,如果您需要做出实际的决定,请考虑多年来一直存在着著名的二进制 LKM(Nvidia 视频适配器的驱动程序似乎是最有名的),但没有人为此提起版权侵权诉讼。此外,在法律之外,Linus Torvalds 因其影响力而表示,二进制形式的 LKM 对他来说是可以接受的。

那么 GPL-ONLY 符号呢?内核开发人员选择了一些符号,用于将 LKM 连接到基本内核,这些符号被指定为 GPL-only。这些符号的名称中包含 "GPL_ONLY",使这种意图显而易见。此外,为了让 Linux 模块加载器允许您的 LKM 使用它们,您必须在您的 LKM 中包含一些代码,据称这会证明您在 GPL 下许可您的模块。

这些可能没有任何法律意义。如果 LKM 不是 Linux 的衍生作品,那么内核开发人员根本没有合法的手段来阻止您将 GPL 注释放在您的代码中并以二进制形式分发它。如果 LKM *是* Linux 的衍生作品,那么符号没有 GPL-only 分类可能不足以授权您在二进制形式的 LKM 中使用它。许可文档没有提到它们。充其量,您可以将 GPL-only 符号用作君子协议,承诺不会起诉您在二进制形式的 LKM 中使用所有其他符号。


14. 相关文档

对于作为 Linux 一部分的模块(即与基本内核一起分发的模块),您有时可以在DocumentationLinux 源代码的子目录中找到文档。

许多 LKM 可以选择绑定到基本内核中。如果这样做,您将通过内核 "命令行" 将参数传递给它们,最基本的形式是通过启动时的提示。The BootPrompt HOWTO by Paul Gortmaker将帮助您。它可以从 Linux 文档项目获得。

不要忘记,Linux 和任何 LKM 的源代码始终是最后手段的文档,也是最值得信赖的。


15. 单个模块

在本章中,我记录了单个 LKM。在可能的情况下,我通过参考特定 LKM 的更权威的文档(可能由维护 LKM 代码的同一个人维护)来做到这一点。


15.1. 可执行解释器

您必须至少有一个绑定到基本内核中的可执行解释器,因为为了加载可执行解释器 LKM,您必须运行一个可执行文件,并且必须有某种东西来解释该可执行文件。

那一个绑定的可执行解释器几乎肯定是 ELF 解释器,因为 Linux 系统中的几乎所有可执行文件都是 ELF。

历史说明:在 Linux 上出现 ELF 之前(大约 1995 年),正常的执行文件格式是 a.out。有一段时间,部分 ELF/部分 a.out 的系统很常见。有些仍然存在。


15.1.1. binfmt_aout:a.out 格式的可执行解释器

a.out 是久负盛名的可执行文件格式,在 Unix 的早期历史中很常见,最初是 Linux 唯一的执行文件格式。直到今天,GNU 编译器的可执行输出文件的默认名称仍然是a.out(无论其格式如何)。

如果您尝试在没有它的情况下运行 a.out 可执行文件,您的exec系统调用将失败,并显示 "无法执行二进制文件" 错误。

没有 LKM 参数。

示例

modprobe binfmt_aout


15.1.2. binfmt_elf:ELF 格式的可执行解释器

ELF 是 Linux 系统上正常的执行文件格式。

您不可能没有将此可执行解释器绑定到基本内核中(如果仅仅因为您的 insmod 可能是 ELF 可执行文件)。然而,在概念上可以将它从基本内核中删除并将其作为 LKM 插入。

没有 LKM 参数。

示例

modprobe binfmt_elf


15.1.3. binfmt_java:Java 字节码的可执行解释器

Java 是一种相对现代的面向对象编程语言。Java 程序传统上被编译成 "Java 字节码",这意味着由 Java 字节码解释器来解释。这种新的对象语言的重点是字节码对象文件是可移植的:虽然不同的系统需要不同的对象格式,但只要每个系统都有一个字节码解释器,它就可以运行字节码对象文件。(当然,这只在一段时间内有效。如果可移植性如此简单,那么今天所有系统都将使用相同的对象格式)。

虽然意图是字节码解释器将作为用户空间程序运行,但使用此 LKM,您可以使 Linux 内核像任何其他可执行格式一样解释 Java 字节码。因此,您可以像运行从 C 编译的程序一样运行从 Java 编译的程序(例如,在命令 shell 提示符下键入其名称)。

实际上,中间字节码语言的优点尚未得到证实,并且将 Java 直接编译为更传统的执行文件格式(例如 ELF)非常常见。如果您这样做,您不需要 binfmt_java

没有 LKM 参数。

示例

modprobe binfmt_java


15.2. 块设备驱动程序

15.2.1. floppy:软盘驱动程序

这是软盘的设备驱动程序。您需要它才能以任何方式访问软盘。

此 LKM 记录在文件README.fdlinux/drivers/block 目录的 Linux 源代码树中。有关详细的最新信息,请直接参考此文件。

请注意,如果您从软盘启动(或可能从软盘启动)或使用软盘上的根文件系统启动,您必须将此驱动程序绑定到基本内核中,因为您的系统需要在有机会插入 LKM 之前就需要它。

示例

  
  modprobe floppy 'floppy="daring two_fdc 0,thinkpad 0x8,fifo_depth"'

只有一个 LKM 参数floppy。但它包含许多子参数。这种不寻常的参数格式的原因是为了与如果驱动程序绑定到基本内核中,您将在内核启动参数中指定相同内容的方式保持一致。

的值floppy是一系列以空格分隔的单词。这些单词中的每一个都是以下以逗号分隔的单词序列之一

asus_pci

将允许的驱动器的位掩码设置为仅允许单元 0 和 1。已过时,因为无论如何这是默认设置

daring

告诉软盘驱动程序您有一个表现良好的软盘控制器。这允许更有效和更流畅的操作,但在某些控制器上可能会失败。这可能会加快某些操作。

0,daring

告诉软盘驱动程序您的软盘控制器应谨慎使用。

one_fdc

告诉软盘驱动程序您只有一个软盘控制器(默认)。

address,two_fdc

告诉软盘驱动程序您有两个软盘控制器。假设第二个软盘控制器位于address。如果第二个控制器位于地址 0x370,并且您使用 'cmos' 选项,则不需要此选项

two_fdc

与上面类似,但使用默认地址

thinkpad

告诉软盘驱动程序您有一台 IBM Thinkpad 型号笔记本电脑。Thinkpad 使用用于磁盘更换线的倒置约定。

0,thinkpad

告诉软盘驱动程序您没有 Thinkpad。

nodma

告诉软盘驱动程序不要使用 DMA 进行数据传输。这是在 HP Omnibooks 上需要的,它们没有用于软盘驱动程序的可行的 DMA 通道。如果您经常收到 "无法分配 DMA 内存" 消息,此选项也很有用。实际上,DMA 内存需要在物理内存中是连续的,因此更难找到,而非 DMA 缓冲区可以在虚拟内存中分配。但是,如果您有一个没有 FIFO 的 FDC(8272A 或 82072),我不建议这样做。(82072A 及更高版本可以)。您还需要至少一台 486 才能使用 nodma。如果您使用 nodma 模式,我建议您还将 FIFO 阈值设置为 10 或更低,以限制数据传输中断的数量。

如果您有一个支持 FIFO 的 FDC,如果它找不到任何支持 DMA 的内存,软盘驱动程序会自动回退到非 DMA 模式。如果您想避免这种情况,请明确指定 "yesdma"。

omnibook

nodma.

yesdma

相同

nofifo

完全禁用 FIFO。如果您在访问软盘时从您的以太网卡(或从其他设备)收到 "总线主控仲裁错误" 消息,则需要这样做。

fifo

启用 FIFO(默认)

threshold,fifo_depth

设置 FIFO 阈值。这主要与 DMA 模式相关。如果这个值更高,软盘驱动程序可以容忍更多的中断延迟,但它会触发更多的中断(即,它会对系统的其余部分施加更多的负载)。如果这个值更低,中断延迟也应该更低(更快的处理器)。较低阈值的好处是中断较少。

要调整 fifo 阈值,请使用 'floppycontrol --messages' 打开 over/underrun 消息。然后访问软盘。如果您收到大量的 "Over/Underrun - retrying" 消息,那么 fifo 阈值太低。尝试使用更高的值,直到您只收到偶尔的 Over/Underrun。

该值必须介于 0 和 0xf 之间(含 0 和 0xf)。

当您插入和删除 LKM 以尝试不同的值时,请记住每次插入 LKM 时都要重新执行 'floppycontrol --messages'。您通常不需要调整 fifo,因为默认值 (0xa) 是合理的。

drive,type,cmos

设置drive的 CMOS 类型为type。如果您有超过两个软盘驱动器(只能在物理 CMOS 中描述两个),或者您的 BIOS 使用非标准 CMOS 类型,则这是强制性的。CMOS 类型为

0

使用物理 CMOS 的值

1

5 1/4 DD

2

5 1/4 HD

3

3 1/2 DD

4

3 1/2 HD

5

3 1/2 ED

6

3 1/2 ED

16

未知或未安装

(注意:ED 驱动器有两种有效的类型。这是因为 5 最初被选择来表示软盘 *磁带*,6 表示 ED 驱动器。 AMI 忽略了这一点,并使用 5 表示 ED 驱动器。这就是软盘驱动程序处理这两种类型的原因)

unexpected_interrupts

当收到意外中断时,打印警告消息。(默认行为)

no_unexpected_interrupts

当收到意外中断时,不打印消息。这在某些视频模式下的 IBM L40SX 笔记本电脑上是必需的。(视频和软盘之间似乎存在交互。意外中断只会影响性能,可以安全地忽略。)

L40SX

no_unexpected_interrupts.

broken_dcl

不要使用磁盘更换线,而是假定每次重新打开设备节点时磁盘都已更换。某些设备的磁盘更换线损坏或不支持时需要此选项。这应被视为一种权宜之计,实际上它会由于不必要的缓存刷新而降低软盘操作效率,并使其稍微变得不可靠。如果您有任何 DCL 问题,请检查您的电缆、连接和跳线设置。但是,已知一些较旧的驱动器以及一些笔记本电脑没有 DCL。

debug

打印调试信息

messages

为某些操作打印信息性消息(磁盘更换通知、关于溢出和欠载的警告以及关于自动检测的警告)

silent_dcl_clear

使用一种噪音较小的方式来清除磁盘更换线(不涉及寻道)。 由 daring 隐含。

nr,irq

告诉驱动程序期望在 IRQnr上发生中断,而不是传统的 IRQ 6。

nr,dma

告诉驱动程序使用 DMA 通道nr而不是传统的 DMA 通道 2。

slow

使用 PS/2 步进速率:PS/2 软盘的步进速率比普通软盘慢得多。有人建议在某些更极端的情况下,速度应约为默认速度的 1/4。

mask,allowed_drive_mask

将允许的驱动器的位掩码设置为mask。 默认情况下,只允许每个软盘控制器的单元 0 和 1。 这是因为某些非标准硬件(华硕 PCI 主板)在访问单元 2 或 3 时会干扰键盘。 此选项已被 'cmos' 选项部分淘汰。

all_drives

将允许的驱动器的位掩码设置为所有驱动器。 如果您有多个驱动器连接到软盘控制器,请使用此选项。


15.2.2. loop: loop 设备驱动程序

此模块允许您挂载存储在常规文件(在另一个文件系统中)中的文件系统。 另一个文件称为后备文件。

一种用法是在不可逆地将其刻录到 CD 上之前测试 ISO 9660 文件系统。 您在 650 MB 常规文件中构建文件系统。 该文件将是 CD 刻录程序的输入。 但是,您可以基于该文件定义一个环回设备作为后备文件,然后直接从后备文件挂载文件系统。

它还可以为您提供一种方便的方式,通过网络传输文件集合。 它就像一个 tar 文件,只是您不必打包和解包它 - 您只需挂载原始文件即可。

有些人会在有时运行 Windows,有时运行 Linux 的机器上使用 loop 设备,以允许他们通过 Windows 系统维护 Linux 系统:将 Linux 根文件系统放在 Windows 可以访问的 FAT 文件系统中的文件中,然后在 Linux 运行时通过 loop 设备挂载 Linux 根文件系统。

您可以将文件系统加密或压缩,或者以任何任意方式编码到后备文件中。 loop 设备在您写入时进行编码(例如,加密),并在您读取时进行解码(例如,解密)。 (另一种更流行的加密和压缩文件系统的策略是使用加密或压缩的文件系统类型,无论是原生的还是由普通文件系统支持的。 Cfs、Tcfs 和 Stegfs 是此类文件系统类型的示例)。

编码系统基于“传输函数”。 中内置了两个传输函数loop模块:标识传输函数(用于正常的非编码情况 - 您在 loop 设备中看到的内容与后备文件中的内容完全相同)和一个简单的 XOR 加密函数。 单独的内核模块可以通过调用loop模块导出的loop_register_transfer()函数来添加任何传输函数。

似乎存在各种提供传输函数以进行压缩和加密(DES、IDEA、Fish 等)的模块。 其中一些似乎是当前 Linux 内核发行版的一部分。 此外,似乎存在各种替代的 loop 设备驱动程序,其中许多也称为loop,其中内置了此类传输函数。

不要将这些 loop 设备与用于机器到自身的网络连接的“环回设备”混淆。 这实际上根本不是一个设备 - 它是一个网络接口。

此模块是一个块设备驱动程序。 您可以通过向其发出 ioctl 来设置 loop 设备,以将文件绑定到它。 发出此 ioctl 的典型程序是 losetup。 有关更多详细信息,请参阅 losetup 的文档。 普通 'mount' 命令上也有一些选项可以在后台执行 loop 设备设置,但是由于这混淆了设置 loop 设备和挂载文件系统这两个逻辑上独立的操作,为了清楚起见,您最好使用 losetup

示例

modprobe loop

模块参数

max_loop

将存在的 loop 设备数量。 与其名称暗示的相反,您指定的数量是始终存在的 loop 设备的数量。 但是,现有设备不一定已配置(绑定到后备文件),因此该数字可以被视为您可以配置的最大 loop 设备数量。

这些 loop 设备的次要编号从 0 开始连续排列。

在 Loopback Encrypted Filesystem HOWTO、Loopback Root Filesystem HOWTO 和 losetup 的手册中,可以找到有关 loop 设备的更多信息。


15.2.3. linear: linear(非 RAID)磁盘阵列设备驱动程序

此驱动程序允许您将多个磁盘分区组合成一个逻辑块设备。

如果您使用此驱动程序,则您的多设备驱动程序将能够使用所谓的线性模式,即它将通过简单地将一个磁盘分区附加到另一个磁盘分区来组合磁盘分区。

请参阅 Software-RAID-HOWTO

示例

modprobe linear

没有模块参数。


15.2.4. raid0: RAID-0 设备驱动程序

此驱动程序允许您将多个磁盘分区组合成一个逻辑块设备。

如果您使用此驱动程序,则您的多设备驱动程序将能够使用所谓的 raid0 模式,即它将以一种使它们均匀填充的方式将磁盘分区组合成一个逻辑设备,此处一个块,彼处一个块。 如果分区位于不同的磁盘上,这将提高吞吐量。

请参阅 Software-RAID-HOWTO

示例

modprobe raid0

没有模块参数。


15.2.5. rd: ramdisk 设备驱动程序

ramdisk 是一种块设备,其存储由系统内存(真实内存;不是虚拟内存)组成。 您可以像使用非常快的磁盘设备一样使用它,也可以在需要设备但没有传统硬件设备可供使用的情况下使用它。

后者的一个常见示例是用于救援系统 - 您用来诊断和修复实际系统的系统。 由于您不想弄乱实际磁盘,因此您在 ramdisk 上运行。 您可能会从外部介质(例如软盘)将数据加载到这些 ramdisk 中。

有时,您会让引导加载程序(例如 lilo)创建一个 ramdisk 并加载数据(可能来自软盘)。 当然,如果您这样做,您将无法使用 ramdisk 驱动程序的 LKM 版本,因为该驱动程序必须在启动时位于内核中。

实际上,ramdisk 在 Linux 中在概念上很简单。 由于缓冲区缓存,磁盘设备通过内存运行。 ramdisk 唯一的区别在于,您永远不会真正通过缓冲区缓存到达实际设备。 这是因为对于 ramdisk,1) 当您第一次访问特定块时,Linux 只是假定它全为零; 以及 2) 设备的缓冲区缓存块永远不会写入设备,因此永远不会被盗用于其他设备。 这意味着读取和写入始终是对缓冲区缓存进行的,永远不会到达设备。

文件中包含有关 ramdisk 的其他信息Documentation/ramdisk.txt位于 Linux 源代码树中。

示例

  modprobe rd

没有可以提供给 LKM 的模块参数,但是如果您将模块绑定到基本内核中,则可以将其传递给内核参数。 请参阅 BootPrompt-HOWTO


15.2.6. xd: XT 磁盘设备驱动程序

在 IBM XT 计算机中使用的非常旧的 8 位硬盘控制器。 不,XT 磁盘支持的存在并不意味着您可以在 IBM XT 上运行 Linux :)。

示例

modprobe xd

没有模块参数。


15.3. SCSI 驱动程序

有关 SCSI 驱动程序的详细信息,请参见 SCSI-2.4-HOWTO

Linux 的 SCSI 功能分三个层实现,并且所有层都有 LKM。

中间是中间层驱动程序或 SCSI 核心。 这由 scsi_mod LKM 组成。 无论您使用什么 SCSI 适配器以及什么类型的设备(磁盘、扫描仪、CD-ROM 驱动器等),它都会执行 SCSI 设备之间通用的所有操作。

每个 SCSI 适配器都对应一个底层驱动程序 - 通常,每个品牌都有一个不同的驱动程序。 例如,Advansys 适配器(由现在为 Connect.com 的公司制造)的底层驱动程序名为 advansys。(如果您比较 ATA(又名 IDE)和 SCSI 磁盘设备,这是一个主要区别 - ATA 足够简单和标准,一个驱动程序可以与所有公司的所有适配器一起使用。 SCSI 的标准化程度较低,因此您应该对任何特定适配器与您的系统完美兼容的信心较少)。

高层驱动程序向内核的其余部分呈现适用于某种类型设备的接口。 例如,磁带设备的 SCSI 高层驱动程序 st 具有倒带的 ioctl。 CD-ROM 驱动器的高层 SCSI 驱动程序 sr 没有。

请注意,您很少需要特定于某个品牌设备的特定高层驱动程序。 在此级别,一个品牌几乎没有与另一个品牌区分开的空间。

值得特别提及的一个 SCSI 高层驱动程序是 sg。 此驱动程序称为“SCSI 通用”驱动程序,它是一个相当薄的层,向内核的其余部分呈现 SCSI 中间层驱动程序的相当原始的表示形式。 通过 SCSI 通用驱动程序运行的用户空间程序(因为它们访问主编号由 sg 注册的设备特殊文件(即 21))对 SCSI 协议有详细的了解,而通过其他 SCSI 高层驱动程序运行的用户空间程序通常甚至不知道什么是 SCSI。 SCSI-Programming-HOWTO 包含 SCSI 通用驱动程序的完整文档。

SCSI 模块的层顺序掩盖了 LKM 彼此依赖的方式以及必须加载它们的顺序。 您始终首先加载中间层驱动程序,最后卸载它。 低层和高层驱动程序可以在此之后以任何顺序加载和卸载,并且它们将自己挂钩到中间层驱动程序并在这两端建立依赖关系。 如果您没有完整的集合,则尝试访问设备时会收到“找不到设备”错误。

大多数 SCSI 底层(适配器)驱动程序没有 LKM 参数;它们通常会自动探测卡设置。 如果您的卡响应某些非常规端口地址,则必须将驱动程序绑定到基本内核并使用内核“命令行”选项。 请参阅 BootPrompt-HOWTO。 或者您可以调整源代码并重新编译。

许多 SCSI 底层驱动程序在drivers/scsiLinux 源代码树中的目录中都有文档,位于名为README.*.


15.3.1. scsi_mod: SCSI 中级驱动程序

示例

modprobe scsi_mod

没有模块参数。


15.3.2. sd_mod: 用于磁盘设备的 SCSI 高级驱动程序

示例

modprobe sd_mod

没有模块参数。


15.3.3. st: 用于磁带设备的 SCSI 高级驱动程序

示例

modprobe st

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO


15.3.4. sr_mod: 用于 CD-ROM 驱动器的 SCSI 高级驱动程序

示例

modprobe sr_mod

没有模块参数。


15.3.5. sg: 用于通用 SCSI 设备的 SCSI 高级驱动程序

请参阅上面对这个特殊高级驱动程序的解释。

示例

modprobe sg

没有模块参数。


15.3.6. wd7000: 用于 7000FASST 的 SCSI 低级驱动程序

示例

modprobe wd7000

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO

此驱动程序自动探测该卡,需要安装 BIOS。


15.3.7. aha152x: 用于 Adaptec AHA152X/2825 的 SCSI 低级驱动程序

示例

modprobe aha152x

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO

此驱动程序自动探测该卡,需要安装 BIOS。


15.3.8. aha1542: 用于 Adaptec AHA1542 的 SCSI 低级驱动程序

示例

modprobe aha1542

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO

此驱动程序仅在 0x330 和 0x334 地址自动探测该卡。


15.3.9. aha1740: 用于 Adaptec AHA1740 EISA 的 SCSI 低级驱动程序

示例

modprobe aha1740

没有模块参数。

此驱动程序自动探测该卡。


15.3.10. aic7xxx: 用于 Adaptec AHA274X/284X/294X 的 SCSI 低级驱动程序

示例

modprobe aic7xxx

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO

此驱动程序自动探测该卡,并且必须启用 BIOS。


15.3.11. advansys: 用于 AdvanSys/Connect.com 的 SCSI 低级驱动程序

示例

modprobe advansys asc_iopflag=1 asc_ioport=0x110,0x330 asc_dbglvl=1

模块参数

asc_iopflag

1

启用端口扫描

0

禁用端口扫描

asc_ioport

用于扫描 AdvanSys SCSI 适配器的 I/O 端口地址

asc_dbglvl

调试级别

0

仅错误

1

高级别跟踪

2-N

详细跟踪

如果您将此驱动程序绑定到基本内核中,则可以通过内核启动参数向其传递参数。请参阅 BootPrompt-HOWTO


15.3.12. in2000: 用于 Always IN2000 的 SCSI 低级驱动程序

示例

modprobe in2000

没有模块参数。

此驱动程序自动探测该卡。不需要 BIOS。


15.3.13. BusLogic: 用于 BusLogic 的 SCSI 低级驱动程序

此驱动程序可以驱动的 BusLogic 卡的列表很长。请阅读文件drivers/scsi/README.BusLogic在 Linux 源代码树中以获取完整信息。

示例

modprobe BusLogic

没有模块参数。

如果您将此驱动程序绑定到基本内核中,则可以通过内核启动参数向其传递参数。请参阅 BootPrompt-HOWTO


15.3.14. dtc: 用于 DTC3180/3280 的 SCSI 低级驱动程序

示例

modprobe dtc

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO

此驱动程序自动探测该卡。


15.3.15. eata: 用于 EATA ISA/EISA 的 SCSI 低级驱动程序

此驱动程序处理 DPT PM2011/021/012/022/122/322。

示例

modprobe eata

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO


15.3.16. eata_dma: 用于 EATA-DMA 的 SCSI 低级驱动程序

此驱动程序处理 DPT、NEC、AT&T、SNI、AST、Olivetti 和 Alphatronix。

此驱动程序处理 DPT Smartcache、Smartcache III 和 SmartRAID。

示例

modprobe eata_dma

没有模块参数。

自动探测适用于所有配置。


15.3.17. eata_pio: 用于 EATA-PIO 的 SCSI 低级驱动程序

此驱动程序处理旧的 DPT PM2001、PM2012A。

示例

  modprobe eata_pio

没有模块参数。


15.3.18. fdomain: 用于 Future Domain 16xx 的 SCSI 低级驱动程序

示例

modprobe fdomain

没有模块参数。

此驱动程序自动探测该卡,需要安装 BIOS。


15.3.19. NCR5380: 用于 NCR5380/53c400 的 SCSI 低级驱动程序

示例

modprobe NCR5380 ncr_irq=xx ncr_addr=xx ncr_dma=xx ncr_5380=1   \
                 ncr_53c400=1
用于端口映射的 NCR5380 板
modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1
用于禁用中断的内存映射 NCR53C400 板
modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1

参数

ncr_irq

驱动程序要服务的 IRQ。255 表示没有或 DMA 中断。254 表示如果命令行被覆盖,则自动探测 IRQ 线。

ncr_addr

I/O 端口地址或内存映射 I/O 地址,以驱动程序要驱动的地址为准

ncr_dma

驱动程序要使用的 DMA 通道

ncr_5380

1 = 设置用于 NCR5380 板

ncr_53c400

1 = 设置用于 NCR53C400 板

如果您将此驱动程序绑定到基本内核中,则可以通过内核启动参数向其传递参数。请参阅 BootPrompt-HOWTO


15.3.20. NCR53c406a: 用于 NCR53c406a 的 SCSI 低级驱动程序

示例

modprobe NCR53c406a

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO


15.3.21. 53c7,8xx.o: 用于 NCR53c7,8xx 的 SCSI 低级驱动程序

示例

modprobe 53c7,8xx

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO

此驱动程序自动探测该卡,需要安装 BIOS。


15.3.22. ncr53c8xx: 用于 PCI-SCS NCR538xx 系列的 SCSI 低级驱动程序

示例

modprobe ncr53c8xx

没有模块参数。


15.3.23. ppa: 用于 IOMEGA 并口 ZIP 驱动器的低级 SCSI 驱动程序

请参阅文件drivers/scsi/README.ppa在 Linux 源代码树中获取详细信息。

示例

modprobe ppa ppa_base=0x378 ppa_nybble=1

参数

ppa_base

PPA 的 I/O 端口的基地址。默认值为 0x378。

ppa_speed_high

数据传输中使用的延迟,以微秒为单位。默认值为 1。

ppa_speed_low

其他操作中使用的延迟,以微秒为单位。默认值为 6。

ppa_nybble

1 = 使用 4 位模式。0 = 不使用。默认值为 0。


15.3.24. pas16: 用于 PAS16 的 SCSI 低级驱动程序

示例

modprobe pas16

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO

此驱动程序自动探测该卡。不需要 BIOS。


15.3.25. qlogicfas: 用于 Qlogic FAS 的 SCSI 低级驱动程序

示例

modprobe qlogicfas

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO


15.3.26. qlogicisp: 用于 Qlogic ISP 的 SCSI 低级驱动程序

示例

modprobe qlogicisp

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO

需要固件。


15.3.27. seagate: 用于 Seagate, Future Domain 的 SCSI 低级驱动程序

此驱动程序适用于 Seagate ST-02 和 Future Domain TMC-8xx。

示例

  modprobe seagate

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO

此驱动程序仅自动探测地址。IRQ 固定为 5。该驱动程序需要安装 BIOS。


15.3.28. t128: 用于 Trantor T128/T128F/T228 的 SCSI 低级驱动程序

示例

  modprobe t128

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO

此驱动程序自动探测该卡。该驱动程序需要安装 BIOS。


15.3.29. u14-34f: 用于 UltraStor 14F/34F 的 SCSI 低级驱动程序

示例

  modprobe u14-34f

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO

此驱动程序自动探测该卡,但探测 0x310 端口。不需要 BIOS。


15.3.30. ultrastor: 用于 UltraStor 的低级 SCSI 驱动程序

示例

modprobe ultrastor

LKM 没有模块参数,但是如果您将此模块绑定到基本内核中,则可以通过 Linux 启动参数传递一些参数。请参阅 BootPrompt-HOWTO


15.4. 网络设备驱动程序

15.4.1. bsd_comp: 用于 PPP 的可选 BSD 压缩器

示例

modprobe bsd_comp

没有模块参数。

此模块依赖于模块 ppp


15.4.2. slhc: 用于 PPP 的 SLHC 压缩器

此模块包含压缩和解压缩 tcp 数据包的例程(用于在低速串行线上进行传输)。

PPP(也是 ISDN-PP)和 SLIP 协议需要这些例程,并且由实现这些协议的 LKM 使用。

示例

modprobe slhc

没有模块参数。


15.4.3. dummy: 虚拟网络接口驱动程序

据说这是一个位桶设备(即,您发送到此设备的流量将被发送到虚无),具有可配置的 IP 地址。它最常用于使您当前未激活的 SLIP 地址看起来像是本地程序的真实地址。

但是,它也可以用作一种环回设备。您为它配置一个特定的 IP 地址,并且您通过此接口发送到该 IP 地址的任何数据包都会返回,并显示为该接口接收到的该 IP 地址的数据包。这对于通常由另一个接口(可能是 PPP 接口)反映的 IP 地址特别有用,但该接口现在已关闭。

您可以拥有多个虚拟接口。它们被命名为dummy0, dummy1等等。

示例

modprobe dummy

没有模块参数。


15.4.4. eql: 串行线负载平衡器

如果您有两个到另一台计算机的串行连接(这通常需要两个调制解调器和两条电话线),并且您在它们上使用 PPP(一种通过电话线发送 Internet 流量的协议)或 SLIP(一种较旧的 PPP 替代方案),您可以使用此驱动程序使它们表现为一个双倍速度的连接。

示例

modprobe eql

没有模块参数。


15.4.5. dlci: 帧中继 DLCI 驱动程序

这实现了帧中继协议;帧中继是一种快速且低成本的方式,可以连接到远程 Internet 访问提供商或形成专用广域网。从您的设备到本地“交换机”(即,帧中继网络的入口点)的一条物理线路可以承载到连接到帧中继网络的其他计算机的几个逻辑点对点连接。要使用帧中继,您需要支持硬件 (FRAD) 和来自 net- tools 包的某些程序,如Documentation/networking/framerelay.txt位于 Linux 源代码树中。

示例

modprobe dlci

没有模块参数。


15.4.6. sdla: Sangoma S502A FRAD 驱动程序

这是 Sangoma S502A、S502E 和 S508 帧中继接入设备的驱动程序。这些是多协议卡,但此驱动程序目前只能驱动帧中继。请阅读Documentation/networking/framerelay.txt位于 Linux 源代码树中。

示例

modprobe sdla

没有模块参数。

此模块依赖于模块 dlci


15.4.7. plip: PLIP 网络接口驱动程序

PLIP(并行线路 Internet 协议)用于创建由两台(或极少数情况下,更多)本地机器组成的迷你网络。并行端口(几乎所有 ISA 后代计算机都具有的连接器,通常用于连接打印机)使用“空打印机”或“Turbo Laplink”电缆连接,这些电缆可以一次传输 4 位,或者使用特殊的 PLIP 电缆(仅在双向并行端口上使用),这些电缆可以一次传输 8 位。电缆最长可达 15 米。如果其中一台机器运行 DOS/Windows 并且安装了一些 PLIP 软件,例如 Crynwr PLIP 数据包驱动程序和 winsock 或 NCSA 的 telnet,也可以这样工作。

请参阅 PLIP-Install-HOWTO

示例

modprobe plip io=0x378 irq=7

参数

io

并行端口驱动程序要驱动的端口地址。

irq

IRQ 驱动程序要服务的 IRQ 号码。默认值为:0x3bc 端口的 IRQ 5、0x378 端口的 IRQ 7 和 0x278 端口的 IRQ 9。

如果您未指定io参数,则驱动程序会探测地址 0x278、0x378 和 0x3bc。


15.4.8. ppp: PPP 网络协议驱动程序

PPP(点对点协议)是在串行端口(带或不带连接的调制解调器)上使用的最常见协议,用于在两台计算机之间创建 IP 网络链路。

除了这个内核驱动程序之外,您还需要运行用户空间程序 pppd

请参阅 PPP-HOWTO

示例

modprobe ppp

没有模块参数。

此模块依赖于模块 slhc

该模块还访问串行设备,这些设备由 serial 模块驱动,因此它也依赖于该模块。此依赖关系未被 depmod 检测到,因此您必须手动声明它或显式加载 serial


15.4.9. slip: SLIP 网络协议驱动程序

SLIP(串行线路 Internet 协议)与 PPP 类似,只是更旧且更简单。

示例

modprobe slip slip_maxdev=1

参数

slip_maxdev

驱动程序一次可以使用的设备的最大数量。默认值为 256。

此模块依赖于模块 slhc

该模块还访问串行设备,这些设备由 serial 模块驱动,因此它也依赖于该模块。此依赖关系未被 depmod 检测到,因此您必须手动声明它或显式加载 serial


15.4.10. baycom: BAYCOM AX.25 无线电业余爱好者驱动程序

这是连接到串行接口或并行接口的 Baycom 样式简单业余无线电调制解调器的驱动程序。该驱动程序适用于 ser12 和 par96 设计。

有关更多信息,请参见 http://www.baycom.org/~tom

示例

modprobe baycom modem=1 iobase=0x3f8 irq=4 options=1

参数

major

驱动程序应使用的主设备号;默认值为 60

modem

第一个通道(次设备号 0)的调制解调器类型

1

ser12

2

par96/par97

iobase

驱动程序要驱动的端口的基地址。 ser12 的常见值为 0x3f8、0x2f8、0x3e8、0x2e8,par96/par97 的常见值为 0x378、0x278、0x3bc。

irq

驱动程序要服务的 IRQ。ser12 的常见值为 3 和 4,par96/par97 的常见值为 7。

options

0

使用硬件 DCD

1

使用软件 DCD


15.4.11. strip: STRIP (Metricom starmode 无线电 IP) 驱动程序

STRIP 是为 MosquitoNet 项目开发的无线电协议,用于使用 Metricom 无线电发送 Internet 流量。Metricom 无线电是小型、电池供电的 100kbit/sec 数据包无线电收发器,大小和重量与无线电话差不多。(您可能还听说过它们被称为“Metricom 调制解调器”,但我们避免使用“调制解调器”一词,因为它误导许多人认为您可以将 Metricom 调制解调器插入电话线并将其用作调制解调器。)您可以在任何带有串行端口的 Linux 机器上使用 STRIP,尽管对于拥有笔记本电脑的人来说,它显然是最有用的。

示例

modprobe strip

没有模块参数。


15.4.12. wavelan: WaveLAN 驱动程序

WaveLAN 卡用于无线以太网类网络。此驱动程序驱动 AT&T GIS 和 NCR WaveLAN 卡。

示例

modprobe wavelan io=0x390 irq=0

参数

io

卡上I/O端口的地址。 默认值为0x390。您可以在卡上设置不同的地址,但不建议这样做。

irq

驱动程序要服务的IRQ。 默认值为0。任何其他值都会被忽略,卡仍然服务于IRQ 0。


15.4.13. wic:WIC无线电IP桥驱动程序

这是WIC并行端口无线电桥的驱动程序。

示例

modprobe wic

看起来设备wic0, wic1发送消息,然后wic2直接关联到相应的lpN端口。


15.4.14. scc:Z8530 SCC kiss仿真驱动程序

这些卡用于将您的Linux机器连接到业余无线电,以便与其他计算机通信。 如果您想使用它,请阅读Documentation/networking/z8530drv.txt在Linux内核源代码树和HAM-HOWTO中。

示例

modprobe scc

没有模块参数。


15.4.15. 8390:通用NS8390以太网驱动程序核心

这是8390以太网芯片的驱动程序代码,许多以太网适配器都基于此芯片。 这不是一个完整的接口驱动程序; 此模块中的例程由特定以太网适配器的驱动程序使用,例如ne3c503

示例

 
modprobe 8390

没有模块参数。


15.4.16. ne:NE2000/NE1000驱动程序

这是老牌的NE2000以太网适配器、其前身NE1000以及所有模拟这个事实标准的通用以太网适配器的驱动程序。 这是一个ISA总线卡。 对于PCI版本,请参阅ne2k-pci模块。

示例

modprobe ne io=0x300 irq=11

参数

io

卡上I/O端口的地址。 此参数是必需的,但您可以指定0x000以使驱动程序自动探测0x300、0x280、0x320、0x340和0x360。

irq

驱动程序要服务的IRQ。 如果您不指定此参数,驱动程序将通过autoIRQ探测来确定它。

bad

值0xBAD表示假设该卡设计不良,因为它不确认重置或没有有效的0x57,0x57签名。 如果您有这样的卡并且不指定此选项,驱动程序将无法识别它。

使用任何其他值,该选项无效。

您可以重复这些选项以指定其他卡。 第n个选项的出现适用于第n个卡。

此模块依赖于模块8390


15.4.17. ne2k-pci:NE2000 PCI驱动程序

这是老牌的NE2000以太网适配器的PCI版本,以及所有模拟这个事实标准的通用以太网适配器的驱动程序。

示例

modprobe ne io=0x300 irq=11

参数

debug

调试消息的级别。 0表示没有消息。 1是默认值。 数字越大,调试消息越多。

options

此选项的值决定了在网络适配器中设置哪些选项。 该值的每一位,表示为二进制数,控制一个选项。 唯一定义的选项是全双工,这是最低有效位的第6位。 使用full_duplex选项更容易。

full_duplex

"1"值将适配器设置为全双工模式。 "0"值将其设置为半双工模式。 如果您在使用options参数指定的标志中包含全双工标志,则full_duplex无效。

您可以重复options发送消息,然后full_duplex参数,每个网络适配器一次,最多可支持8个网络适配器。

此驱动程序可以驱动以下芯片组

  • RealTek RTL-8029

  • Winbond 89C940

  • Winbond W89C940F

  • KTI ET32P2

  • NetVin NV5000SC

  • Via 86C926

  • SureCom NE34

  • Holtek HT80232

  • Holtek HT80229

  • Compex RL2000

此模块依赖于模块8390


15.4.18. 3c501:3COM 3c501以太网驱动程序

这是3COM的3c501以太网适配器的驱动程序。

示例:modprobe 3c501 io=0x280 irq=5

参数

io

卡上I/O端口的地址。

irq

驱动程序要服务的IRQ。 默认值为5。

如果您不指定I/O端口,驱动程序将探测地址0x280和0x300。


15.4.19. 3c503:3COM 3c503驱动程序

这是3COM的3c503以太网适配器的驱动程序。

示例

modprobe 3c503 io=0x300 irq=5 xcvr=0

参数

io

卡上I/O端口的地址。

irq

驱动程序要服务的IRQ。

xcvr

确定是否使用外部收发器。

0

no

1

yes

如果您不指定I/O端口,驱动程序将探测地址0x300、0x310、0x330、0x350、0x250、0x280、0x2A0和0x2E0。

此模块依赖于模块8390


15.4.20. 3c505:3COM 3c505驱动程序

这是3COM的3c505以太网适配器的驱动程序。

示例

modprobe 3c503 io=0x300 irq=5 xcvr=0

参数

io

卡上I/O端口的地址。

irq

驱动程序要服务的IRQ。

如果您不指定I/O端口,驱动程序将探测地址0x300、0x280和0x310。

此模块依赖于模块8390


15.4.21. 3c507:3COM 3c507驱动程序

这是3COM的3c507以太网适配器的驱动程序。

示例

modprobe 3c503 io=0x300 irq=5 xcvr=0

参数

io

卡上I/O端口的地址。

irq

驱动程序要服务的IRQ。

如果您不指定I/O端口,驱动程序将探测地址0x300、0x320、0x340和0x280。

此模块依赖于模块8390


15.4.22. 3c509:3COM 3c509/3c579驱动程序

这是3COM的3c507和3c579以太网适配器的驱动程序。

示例

modprobe 3c503 io=0x300 irq=5 xcvr=0

参数

io

卡上I/O端口的地址。

irq

驱动程序要服务的IRQ。

模块加载时探测仅在EISA上可靠有效,ISA ID-PROBE不可靠! 现在将此驱动程序绑定到基本内核中,如果您需要在ISA总线机器上进行自动探测。


15.4.23. 3c59x:3COM 3c590系列“Vortex”驱动程序

这是以下3COM以太网适配器的驱动程序

  • 3c590 Vortex 10Mbps。

  • 3c595 Vortex 100baseTX。

  • 3c595 Vortex 100baseT4。

  • 3c595 Vortex 100base-MII。

  • EISA Vortex 3c597。

示例

modprobe 3c59x debug=1 options=0,,12

参数

debug

选择调试消息级别的数字。

options

这是一个由逗号分隔的选项数字字符串。 对于驱动程序驱动的每个适配器,都有一个选项编号(对于您在系统中具有由该驱动程序驱动的多种类型的以太网适配器的情况)。 选项编号的顺序是由PCI BIOS分配的卡的顺序。

每个数字表示一个二进制值。 在该值中,较低的3位是媒体类型

0

10baseT

1

10Mbs AUI

2

未定义

3

10base2 (BNC)

4

100base-TX

5

100base-FX

6

MII (尚未可用)

7

使用默认设置

下一位(“8”位)对于全双工为打开,对于半双工为关闭。

下一位(“16”位)打开以启用总线主控,仅用于实验目的。

设备驱动程序实现的详细信息位于源文件的顶部。


15.4.24. wd:Western Digital/SMC WD80*3驱动程序

这是Western Digital WD80*3以太网适配器的驱动程序。

示例

modprobe wd io=0x300 irq=5 mem=0x0D0000 mem_end=0x0D8000

参数

io

卡上I/O端口的地址。

irq

驱动程序要服务的IRQ。

mem

共享内存地址

mem_end

共享内存的末尾(其后的下一个字节的地址)。

如果您不指定I/O端口,驱动程序将探测0x300、0x280、0x380和0x240。

如果您不指定IRQ,驱动程序会从适配器的EEPROM中读取它,对于没有它的旧卡,驱动程序使用autoIRQ。

该驱动程序依赖于模块8390


15.4.25. smc-ultra:SMC Ultra/EtherEZ驱动程序

这是SMC Ultra/EtherEZ以太网适配器的驱动程序。

示例

modprobe smc-ultra io=0x200 irq=5

参数

io

卡上I/O端口的地址。 如果您不指定此值,适配器将探测0x200、0x220、0x240、0x280、0x300、0x340和0x380。

irq

驱动程序要服务的IRQ。 默认值是从适配器的EEPROM读取的值。

该驱动程序依赖于模块8390


15.4.26. smc9194:SMC 9194驱动程序

这是SMC的9000系列以太网卡的驱动程序。

示例

modprobe smc9194 io=0x200 irq=5 ifport=0

参数

io

卡上I/O端口的地址。 如果您不指定此值,适配器将探测0x200、0x220等,直到0x3E0。

irq

驱动程序要服务的IRQ。

ifport

以太网类型。

0

自动检测

1

TP

2

AUI(或10base2)

调试级别可以在源代码中设置。


15.4.27. at1700:AT1700驱动程序

这是AT1700以太网适配器的驱动程序。

示例

modprobe at1700 io=0x260 irq=5

参数

io

卡上I/O端口的地址。 如果您不指定此值,适配器将探测0x260、0x280、0x2A0、0x240、0x340、0x320、0x380和0x300。

irq

驱动程序要服务的IRQ。


15.4.28. e2100:Cabletron E21xx驱动程序

示例

modprobe e2100 io=0x300 irq=5 mem=0xd0000 xcvr=0

参数

io

卡上I/O端口的地址。 如果您不指定此值,适配器将探测0x300、0x280、0x380和0x220。

irq

卡要生成的IRQ以及驱动程序要服务的IRQ。(驱动程序在卡中设置此值)。

mem

共享内存地址。 默认值为0xd0000。

xcvr

0

不要选择外部收发器

1

选择外部收发器

此模块依赖于模块8390


15.4.29. depca:DEPCA、DE10x、DE200、DE201、DE202、DE422驱动程序

这是DEPCA、DE10x、DE200、DE201、DE202和DE422以太网适配器的驱动程序。

示例

modprobe depca io=0x200 irq=7

参数

io

卡上I/O端口的地址。 如果您不指定此值,适配器将探测ISA机器上的0x300和0x200或EISA机器上的0x0c00。

irq

驱动程序要服务的IRQ。 默认值为7。


15.4.30. ewrk3:EtherWORKS 3 (DE203, DE204, DE205) 驱动程序

这是EtherWORKS 3 (DE203, D3204, 和 DE205) 以太网适配器的驱动程序。

示例

modprobe ewrk3 io=0x300 irq=5

io

卡上I/O端口的地址。 默认值为0x300。

irq

驱动程序要服务的IRQ。 默认值为5。

在EISA总线上,此驱动程序执行EISA探测。

在ISA总线上,当作为LKM加载时,此驱动程序不执行自动探测。 但是,如果您将其绑定到基本内核中,它将探测地址0x100、0x120等,直到0x3C0,除了0x1E0和0x320。


15.4.31. eexpress:EtherExpress 16驱动程序

这是EtherExpress 16以太网适配器的驱动程序。

示例

modprobe eexpress io=0x300 irq=5

参数

io

卡上I/O端口的地址。 如果您不指定此值,适配器将探测0x300、0x270、0x320和0x340。 1

irq

驱动程序要服务的IRQ。 默认值是从适配器的EEPROM读取的值。


15.4.32. eepro:EtherExpressPro驱动程序

这是EtherExpressPro以太网适配器的驱动程序。

示例

modprobe eepro io=0x200 irq=5

参数

io

卡上I/O端口的地址。 如果您不指定此值,适配器将探测0x200、0x240、0x280、0x2C0、0x300、0x320、0x340和0x360。

irq

驱动程序要服务的IRQ。


15.4.33. fmv18k:Fujitsu FMV-181/182/183/184驱动程序

这是Fujitsu FMV-181、FMV-182、FMV-183和FMV-184以太网适配器的驱动程序。

示例

modprobe fmv18x io=0x220 irq=5

参数

io

卡上I/O端口的地址。 如果您不指定此值,适配器将探测0x220、0x240、0x260、0x280、0x2a0、0x2c0、0x300和0x340。

irq

驱动程序要服务的IRQ。


15.4.34. hp-plus:HP PCLAN+ (27247B 和 27252A) 驱动程序

这是HP的PCLAN+ (27247B 和 27252A) 以太网适配器的驱动程序。

示例

modprobe hp-plus io=0x200 irq=5

参数

io

卡上I/O端口的地址。 如果您不指定此值,适配器将探测0x200、0x240、0x280、0x2C0、0x300、0x320和0x340。

irq

驱动程序要服务的IRQ。 默认值是驱动程序从适配器的配置寄存器中读取的值。

此模块依赖于模块8390


15.4.35. hp:HP PCLAN (27245, 27xxx) 驱动程序

这是HP的PCLAN(27245和其他27xxx系列)以太网适配器的驱动程序。

示例

modprobe hp io=0x300 irq=5

参数

io

卡上I/O端口的地址。 如果您不指定此值,适配器将探测0x300、0x320、0x340、0x280、0x2C0、0x200和0x240。

irq

驱动程序要服务的IRQ。 如果您不指定此参数,驱动程序将通过autoIRQ探测来确定它。

此模块依赖于模块8390


15.4.36. hp100:HP 10/100VG PCLAN (ISA, EISA, PCI) 驱动程序

这是HP的10/100VG PCLAN以太网适配器的驱动程序。 它适用于ISA、EISA和PCI版本。

示例

modprobe hp100 hp100_port=0x100

参数

hp100_port

卡上 I/O 端口的基地址。如果您未指定此项,驱动程序会在 ISA 总线上自动探测 0x100、0x120 等直到 0x3E0。它会在 EISA 总线上进行 EISA 探测。


15.4.37. eth16i:ICL EtherTeam 16i/32 驱动程序

这是 ICL EtherTeam 16i (eth16i) 和 32i (eth32i) 以太网适配器的驱动程序。

示例

modprobe eth16i io=0x2a0 irq=5

参数

io

卡上 I/O 端口的地址。如果您未指定此项,适配器会探测以下地址。对于 eth16i 适配器:0x260、0x280、0x2A0、0x340、0x320、0x380 和 0x300。对于 eth32i:0x1000、0x2000、0x3000、0x4000、0x5000、0x6000、0x7000、0x8000、0x9000、0xA000、0xB000、0xC000、0xD000、0xE000 和 0xF000。

irq

驱动程序要服务的IRQ。 如果您不指定此参数,驱动程序将通过autoIRQ探测来确定它。


15.4.38. ni52:NI5210 驱动程序

这是 NI5210 以太网适配器的驱动程序。

示例

modprobe ni52 io=0x360 irq=9 memstart=0xd0000 memend=0xd4000


15.4.39. ac3200:Ansel Communications EISA 3200 驱动程序

这是 Ansel Communications EISA 3200 以太网适配器的驱动程序。

示例

modprobe ac3200

此模块依赖于模块8390


15.4.40. apricot:Apricot Xen-II 板载以太网驱动程序

示例

modprobe apricot io=0x300 irq=10

参数

io

卡上基本 I/O 端口的地址。

irq

驱动程序将要服务的 IRQ。


15.4.41. de4x5:DE425、DE434、DE435、DE450、DE500 驱动程序

这是 DE425、DE434、DE435、DE450 和 DE500 以太网适配器的驱动程序。

示例

 
modprobe de4x5 io=0x000b irq=10 is_not_dec=0

参数

io

基本 I/O 端口的地址。

irq

驱动程序要服务的IRQ。

is_not_dec

对于使用 DEC 21040、21041 或 21140 芯片的非 DEC 卡,请将其设置为 1。


15.4.42. tulip:DECchip Tulip (dc21x4x) PCI 驱动程序

示例

modprobe tulip

阅读Documentation/networking/tulip.txt位于 Linux 源代码树中。


15.4.43. dgrs:Digi Intl RightSwitch SE-X 驱动程序

这是 Digi International RightSwitch SE-X EISA 和 PCI 板卡的驱动程序。 这些板卡具有一个 4 口 (EISA) 或 6 口 (PCI) 以太网交换机和一个 NIC 组合在一块板卡上。

有一个工具可以设置每个端口上的输入和输出数据包过滤器,称为 dgrsfilt

管理工具可让您以图形方式观看性能,以及设置 SNMP 代理 IP 和 IPX 地址、IEEE 生成树和老化时间。这些也可以在加载驱动程序时从命令行设置。

还有一个配套的管理工具,称为 xrightswitch

示例

modprobe dgrs debug=1 dma=0 spantree=0 hashexpire=300 ipaddr=199,86,8,221
modprobe ipxnet=111

参数

debug

要打印的调试消息级别

dma

0

禁用 PCI 卡上的 DMA

1

启用 PCI 卡上的 DMA

spantree

0

禁用 IEEE 生成树

1

启用 IEEE 生成树

hashexpire

更改地址老化时间,以秒为单位。默认值为 300。

ipaddr

SNMP 代理 IP 地址。值是以点分十进制表示的 IP 地址,但使用逗号代替句点。

ipxnet

SNMP 代理 IPX 网络号


15.4.44. de600:D-Link DE600 袖珍适配器驱动程序

这是 D-Link DE600 袖珍以太网适配器的驱动程序。

示例

modprobe de600 de600_debug=0

参数

de600_debug

驱动程序期望适配器位于端口 0x378 并生成 IRQ 7。 这与 DOS 相同lpt1设备。这些是编译时选项。


15.4.45. de620:D-Link DE620 袖珍适配器驱动程序

这是 D-Link DE620 袖珍以太网适配器的驱动程序。

示例

modprobe de620 bnc=0 utp=0 io=0x378 irq=7

参数

bnc

1

网络是 10Base2

0

网络不是 10Base2

utp

1

网络是 10BaseT

0

网络不是 10BaseT

io

端口驱动程序要驱动的 I/O 端口地址。默认为 0x378。

irq

驱动程序要服务的 IRQ。默认为 7。

您不能同时指定bnc=1发送消息,然后utp=1.


15.4.46. ibmtr:基于 Tropic 芯片组的令牌环适配器驱动程序

示例

modprobe ibmtr io=0xa20 irq=5

参数

io

端口驱动程序要驱动的 I/O 端口地址。默认为 0xa20。

irq

驱动程序要服务的 IRQ。默认情况下,驱动程序通过 autoIRQ 探测确定 IRQ。


15.4.47. arcnet:ARCnet 驱动程序

阅读其中的精细信息Documentation/networking/arcnet.txt在 Linux 源代码树中。还有 Arcnet 硬件信息arcnet-hardware.txt位于相同的位置。

示例

modprobe arcnet io=0x300 irq=2 shmem=0xd0000 device=arc1

参数

io

端口驱动程序要驱动的 I/O 端口地址。如果您未指定此项,驱动程序会探测地址 0x300、0x2E0、0x2F0、0x2D0、0x200、0x210、0x220、0x230、0x240、0x250、0x260、0x270、0x280、0x290、0x2A0、0x2B0、0x2C0、0x310、0x320、0x330、0x340、0x350、0x360、0x370、0x380、0x390、0x3A0、0x3E0 和 0x3F0。

irq

驱动程序要服务的 IRQ。默认情况下,驱动程序通过 autoIRQ 探测确定 IRQ。

device

设备名称。


15.4.48. isdn:基本 ISDN 功能

此模块提供 ISDN 适配器驱动程序使用的 ISDN 功能。

设置 ISDN 网络是一项复杂的任务。阅读中的文档Documentation/isdn位于 Linux 源代码树中。

示例

modprobe isdn

没有模块参数。

此模块依赖于模块 slhc


15.4.49. icn:ICN 2B 和 4B 驱动程序

这是 ICN 2B 和 ICN 4B ISDN 适配器的驱动程序。

示例

modprobe icn portbase=0x320 membase=0xd0000 icn_id=idstring icn_id2=idstring2

参数

portbase

适配器上基本 I/O 端口的地址。默认为 0x320。

membase

共享内存的地址。默认为 0xd0000。

icn_id

第一个适配器的 idstring。必须以字符开头!此参数是必需的。

icn_id2

第二个适配器的 idstring。必须以字符开头!对于双卡,此参数是必需的。

此模块依赖于模块 isdn


15.4.50. pcbit:PCBIT-D 驱动程序

这是 PCBIT-D ISDN 适配器驱动程序。

示例

modprobe pcbit mem=0xd0000 irq=5

参数

mem

共享内存地址。默认为 0xd0000

irq

驱动程序要服务的IRQ。 默认值为5。

此模块依赖于模块 isdn


15.4.51. teles:Teles/NICCY1016PC/Creatix 驱动程序

这是 Teles/NICCY1016PC/Creatix ISDN 适配器的驱动程序。它可以驱动多达 16 个卡。

示例

modprobe teles io=0xd0000,15,0xd80,2 teles_id=idstring

参数

io

这是一个包含所有参数的集合。它的语法是io=card1options [,card2options ,...] 其中card1options是第一个卡的一组选项,依此类推。

的语法card1options等等是sharedmem, irq, portbase, dprotocol

sharedmem

共享内存的地址。默认值为 0xd0000

irq

驱动程序要服务的 IRQ。

portbase

基本 I/O 端口的地址。

dprotocol

卡的 D 通道协议

1

1TR6

2

EDSS1。这是默认值。

teles_id

用于通过实用程序访问和在使用线路监视器时进行识别的驱动程序 ID。值必须以字符开头!默认值:无。

驱动程序从端口、irq 和共享内存地址确定卡类型

  • port == 0,共享内存 != 0 -> Teles S0-8

  • port != 0,共享内存 != 0 -> Teles S0-16.0

  • port != 0,共享内存 == 0 -> Teles S0-16.3

此模块依赖于模块 isdn


15.5. CDROM 设备驱动程序

15.5.1. aztcd:Aztech/Orchid/Okano/Wearnes/TXC/CDROM 驱动程序

这是用于 Aztech、Orchid、Okano、Wearnes、TXC 和 CDROM 设备的驱动程序(这些设备具有特殊的非 SCSI 非 ATA 接口)。

示例

  modprobe aztcd aztcd=0x340

参数

aztcd

基本 I/O 端口的地址

阅读Documentation/cdrom/aztcd在 Linux 源代码树中,以获取完整信息。


15.5.2. gscd:Goldstar R420 CDROM 驱动程序

这是 Goldstar R420 CDROM 驱动器的驱动程序,它不使用 ATA 或 SCSI 接口。

示例

modprobe gscd gscd=0x340

参数

gscd

基本 I/O 端口的地址。默认值为 0x340,这适用于大多数应用程序。您可以使用 Goldstar 接口卡上的 PN801-1 到 PN801-4 跳线选择驱动器的地址。合适的设置包括:0x300、0x310、0x320、0x330、0x340、0x350、0x360、0x370、0x380、0x390、0x3A0、0x3B0、0x3C0、0x3D0、0x3E0 和 0x3F0。


15.5.3. sbpcd:Sound Blaster CDROM 驱动程序

这是 Matsushita、Panasonic、Creative、Longshine 和 TEAC CDROM 驱动器的驱动程序,这些驱动器不通过 ATA 或 SCSI 连接。

示例

modprobe sbpcd sbpcd=0x340

参数

sbpcd

基本 I/O 端口的地址

另一个参数是 SBPRO 设置,如中所述Documentation/cdrom/sbpcd位于 Linux 源代码树中。


15.5.4. mcd:Mitsumi CDROM 驱动程序

这是 Mitsumi CDROM 驱动器的驱动程序,这些驱动器不通过 ATA 或 SCSI 连接。它不处理 XA 或多会话。

示例

modprobe mcd mcd=0x300,11,0x304,5

参数

mcd

这是一个以逗号分隔的 i/o 基地址和 IRQ 列表,成对出现。


15.5.5. mcdx:Mitsumi XA/多会话驱动程序

此驱动程序类似于 mcd,只是它具有 XA 和多会话功能。

示例

modprobe mcdx mcdx=0x300,11,0x304,5


15.5.6. optcd:Optics Storage DOLPHIN 8000AT CDROM 驱动程序

这是 Optics Storage 的所谓 "dolphin" CDROM 驱动器的驱动程序,带有 34 针 Sony 兼容接口。对于 ATA 兼容的 Optics Storage 8001 驱动器,您需要 ATAPI CDROM 驱动程序。该驱动程序似乎也适用于 Lasermate CR328A。

示例

modprobe optcd optcd=0x340

参数

optcd

基本 I/O 端口的地址


15.5.7. cm206:Philips/LMS CM206 CDROM 驱动程序

这是 Philips/LMS cm206 CDROM 驱动器与 cm260 主机适配器卡结合使用的驱动程序。

示例

modprobe cm206 cm206=0x300,11

参数

cm206

驱动程序要驱动的基本 I/O 端口的地址和驱动程序要服务的 IRQ,以逗号分隔。您以任何顺序放置它们都没关系,您可以只指定一个,在这种情况下,另一个将使用默认值。


15.5.8. sjcd:Sanyo CDR-H94A CDROM 驱动程序

示例

modprobe sjcd sjcd_base=0x340

参数

sjcd_base

驱动程序要驱动的基本 I/O 端口的地址。默认为 0x340。

该驱动程序不使用 IRQ,也不使用 DMA 通道。


15.5.9. isp16:ISP16/MAD16/Mozart 软配置 cdrom 驱动程序

这是 ISP16 或 MAD16 或 Mozart 软配置 cdrom 接口的驱动程序。

示例

modprobe isp16 isp16_cdrom_base=0x340 isp16_cdrom_irq=3
         isp16_cdrom_dma=0 isp16_cdrom_type=Sanyo

参数

isp16_cdrom_base

驱动程序要驱动的基本 I/O 端口的地址。有效值为 0x340、0x320、0x330 和 0x360。

isp16_cdrom_irq

驱动程序要服务的 IRQ。有效值为 0、3、5、7、9、10 和 11。

isp16_cdrom_dma

驱动程序要与设备一起使用的 DMA 通道。有效值为 0、3、5、6 和 7。

isp16_cdrom_type

正在驱动的设备类型。有效值为noisp16, Sanyo, Panasonic, Sony发送消息,然后Mitsumi。请注意,这些值区分大小写。


15.5.10. cdu31a:Sony CDU31A/CDU33A CDROM 驱动程序

示例

  modprobe cdu31a cdu31a_port=0x340 cdu31a_irq=5

参数

cdu31a_port

驱动程序要驱动的基本 I/O 端口的地址。此参数是必需的。

cdu31a_irq

驱动程序要服务的 IRQ。如果您未指定此项,驱动程序将不使用中断。


15.5.11. sonycd535:Sony CDU535 CDROM 驱动程序

示例

modprobe sonycd535 sonycd535=0x340

参数

sonycd535

驱动程序要驱动的基本 I/O 端口的地址。


15.6. 文件系统驱动程序

15.6.1. minix:Minix 文件系统驱动程序

示例

modprobe minix

没有模块参数。


15.6.2. ext:"Extended" 文件系统驱动程序

示例

modprobe ext

没有模块参数。


15.6.3. ext2:"Second extended" 文件系统驱动程序

示例

modprobe ext2

没有模块参数。


15.6.4. xiafs:xiafs 文件系统驱动程序

示例

modprobe xiafs

没有模块参数。


15.6.5. fat:DOS FAT 文件系统功能

该模块为MSDOS和VFAT文件系统驱动程序提供服务。

示例

modprobe fat

没有模块参数。


15.6.6. msdos: MSDOS文件系统驱动程序

示例

modprobe msdos

没有模块参数。

该模块依赖于模块 fat


15.6.7. vfat: VFAT (Windows-95) 文件系统驱动程序

示例

modprobe vfat

没有模块参数。

该模块依赖于模块 fat


15.6.8. umsdos: UMSDOS 文件系统驱动程序

这是 UMSDOS 文件系统类型的驱动程序,它是一种构建在 MSDOS FAT 文件系统之上的类 Unix 风格的文件系统。

示例

modprobe vfat

没有模块参数。

该模块依赖于 fatmsdos 模块。


15.6.9. nfs: NFS 文件系统驱动程序

示例

modprobe nfs

没有模块参数。


15.6.10. smbfs: SMB 文件系统驱动程序

SMBFS 是一种具有 SMB 协议接口的文件系统类型。 这是 Windows for Workgroups、Windows NT 或 Lan Manager 相互通信所使用的协议。 SMBFS 的灵感来自 Andrew Tridgell 编写的 Samba 程序,该程序可以将任何 Unix 主机变成 DOS 或 Windows 客户端的文件服务器。 请访问 ftp://nimbus.anu.edu.au/pub/tridge/samba/ 了解这个有趣的程序套件以及关于 SMB 和基于 TCP/IP 的 NetBIOS 的更多信息。 在那里您还可以找到关于诸如 netbios 名称或共享等概念的解释。

要使用 SMBFS,您需要一个特殊的挂载程序,可以在 ksmbfs 包中找到,地址是 ftp://ibiblio.org/pub/Linux/system/Filesystems/smbfs

示例

modprobe smbfs

没有模块参数


15.6.11. ncpfs: NCP (Netware) 文件系统驱动程序

NCPFS 是一种具有 NCP 协议接口的文件系统类型,由 Novell Corporation 为其 NetWare 产品设计。 NCP 在功能上类似于 TCP/IP 社区中使用的 NFS。 要挂载 Netware 文件系统,您需要一个特殊的挂载程序,可以在 ncpfs 包中找到。 ncpfs 的主页是 ftp.gwdg.de/pub/linux/misc/ncpfs,但 Ibiblio 及其许多镜像站点也将提供它。

相关产品是 LinwareMars_nwe,它们将为 Linux 提供部分 NetWare 服务器功能。

Mars_nwe 可以在 ftp.gwdg.de/pub/linux/misc/ncpfs 上找到。

示例

modprobe ncpfs

没有模块参数。

该模块依赖于模块 ipx


15.6.12. isofs: ISO 9660 (CDROM) 文件系统驱动程序

示例

modprobe isofs

没有模块参数。


15.6.13. hpfs: OS/2 HPFS 文件系统驱动程序

此 OS/2 HPFS 文件系统驱动程序仅提供只读访问。

示例

modprobe hpfs

没有模块参数。


15.6.14. sysv: System V 和 Coherent 文件系统驱动程序

这是 Linux 的 SystemV/Coherent 文件系统类型的实现。

它实现了所有以下文件系统:

  • Xenix FS

  • SystemV/386 FS

  • Coherent FS

示例

modprobe sysv

没有模块参数。


15.6.15. affs: Amiga FFS 文件系统驱动程序

示例

modprobe affs

没有模块参数。


15.6.16. ufs: UFS 文件系统驱动程序

显然用于挂载具有 FreeBSD 和/或 Sun 分区的磁盘。 除了源代码之外,没有其他文档。

此文件系统驱动程序仅提供只读访问。

示例

modprobe ufs

没有模块参数。


15.7. 杂项设备驱动程序

15.7.1. misc:用于“杂项”字符设备的设备驱动程序

一大堆设备类型在系统中出现的数量不足以拥有自己的主设备号,它们共享主设备号 10,统称为“杂项”字符设备。 该模块提供了服务于该主设备号的公共接口,但针对特定设备类型存在单独的驱动程序。 这些驱动程序向此驱动程序注册自身。

示例

modprobe misc

没有模块参数。


15.8. 串行设备驱动程序

15.8.1. serial:串行通信端口 (UART) 设备驱动程序

该驱动程序驱动传统的串行端口 (UART),但不驱动某些专门的高性能多端口设备。

注意:serial 是其他模块(例如 pppslip)所必需的。 此外,它也是串行鼠标以及 gpm 所必需的。 但是,这并不是模块处理工具可以检测到的常规依赖关系,因此您必须手动加载 serial

示例

modprobe serial

没有模块参数。


15.8.2. cyclades:Cyclades 异步多路复用器设备驱动程序

示例

  modprobe cyclades

没有模块参数。

智能板还需要将它们的固件代码下载到其中。 这是通过驱动程序包中提供的用户级别应用程序 stlload 完成的。 在放置软件包文件的任何位置编译此程序,方法是键入 make。 然后,以最简单的形式,您可以在此目录中键入 stlload,这将把固件下载到板 0(假设板 0 是 EasyConnection 8/64 板)。 要下载到 ONboard、Brumby 或 Stallion,请执行以下操作:

阅读文件中的信息Documentation/stallion.txt位于 Linux 源代码树中。


15.8.3. stallion:Stallion EasyIO 或 EC8/32 设备驱动程序

智能板还需要将它们的固件代码下载到其中。 这是通过驱动程序包中提供的用户级别应用程序 stlload 完成的。

阅读文件中的信息Documentation/stallion.txt位于 Linux 源代码树中。

示例

  modprobe stallion

没有模块参数。


15.8.4. istallion:Stallion EC8/64、ONboard、Brumby 设备驱动程序

智能板还需要将它们的固件代码下载到其中。 这是通过驱动程序包中提供的用户级别应用程序 stlload 完成的。

阅读 /usr/src/linux/drivers/char/README.stallion 中的信息。

示例

modprobe istallion

没有模块参数。


15.8.5. riscom8:SDL RISCom/8 卡设备驱动程序

示例

modprobe riscom8 iobase=0xXXX iobase1=0xXXX iobase2=...

该驱动程序一次最多可以驱动 4 个板。


15.9. 并行设备驱动程序

15.9.1. lp:并行打印机设备驱动程序

示例

  modprobe lp.o io=0x378 irq=0

该驱动程序探测端口 0x278、0x378 和 0x3bc。

注意:加载没有参数的 lp 将会占用所有并行端口。


15.10. 总线鼠标设备驱动程序

15.10.1. atixlmouse:ATIXL 总线鼠标驱动程序

示例

modprobe atixlmouse

没有参数。

该模块依赖于模块 misc


15.10.2. busmouse:Logitech 总线鼠标驱动程序

示例

modprobe busmouse

没有模块参数。

该模块依赖于模块 misc


15.10.3. msbusmouse:Microsoft 总线鼠标驱动程序

示例

modprobe msbusmouse

没有模块参数。

该模块依赖于模块 misc


15.10.4. psaux:PS/2 鼠标(又名“辅助设备”)驱动程序

示例

modprobe psaux

没有模块参数。

该模块依赖于模块 misc


15.11. 磁带设备驱动程序

对于 SCSI 磁带设备驱动程序,请参见 第 15.3 节。 没有用于 QIC-02 磁带设备的 LKM,但是您可以将一个设备驱动程序绑定到基本内核中。


15.11.1. ftape:软盘磁带 (QIC-80/Travan) 设备驱动程序

示例

modprobe ftape tracing=3

可选参数tracing (跟踪)可以采用以下值

0

bugs (错误)

1

+ errors (错误)

2

+ warnings (警告)

3

+ information (信息)

4

+ more information (更多信息)

5

+ program flow (程序流程)

6

+ fdc/dma info (fdc/dma 信息)

7

+ data flow (数据流)

8

+ everything else (其他所有信息)

默认值为 3。


15.12. 看门狗定时器

15.12.1. WDT:WDT 看门狗定时器设备驱动程序

示例

modprobe wdt

没有模块参数。

设备地址硬编码为 0x240。 IRQ 硬编码为 14。

该模块依赖于模块 misc


15.12.2. softdog:软件看门狗定时器

示例

  modprobe softdog

没有模块参数。

该模块依赖于模块 misc


15.12.3. pcwd:Berkshire Products PC 看门狗驱动程序

示例

modprobe pcwd

没有模块参数。

该模块依赖于模块 misc


15.13. 声卡设备驱动程序

配置声音是一项复杂的任务。 阅读目录中的文件Documention/sound位于 Linux 源代码树中。

示例

modprobe sound

选项: dma_buffsize=32768


16. 本文档的维护

本 HOWTO 由 Bryan Henderson 热心维护如果您发现任何不正确或不完整的地方,或者无法理解某些内容,Bryan 希望知道,以便下一个读者可以免去您所遇到的麻烦。

本文档的源代码是 DocBook SGML,可以从 Linux Documentation Project 获取。


17. 历史

我(在 2001 年)从 Laurie Tischler 在 1997 年发布的同名 HOWTO 中派生出了本文档。 虽然我保留了原始文档中的所有信息(在仍然有用的情况下),但我完全重写了演示文稿,并添加了很多其他信息。 原始 HOWTO 的主要目的是记录 LKM 参数。

原始 HOWTO 于 1996 年 6 月 20 日首次发布(版本 1.0),并于 1996 年 10 月 20 日发布了第二个版本(1.1)。

Bryan 重写后的第一个版本于 2001 年 6 月发布。


18. 版权

以下是 Lauri Tischler 在原始文档中发布的版权声明,本文档由此派生

本文档的版权归 Lauri Tischler 所有,1996©。 允许制作和分发本文档的完整副本,前提是版权声明和此许可声明保留在所有副本上。

允许复制和分发本文档的修改版本,但须遵守完整复制的条件,前提是此版权声明与原始文档中的完全相同,并且整个由此产生的派生作品均根据与此声明相同的许可声明的条款分发。

允许在上述修改版本条件下将本文档翻译成另一种语言。

本文档的当前维护者和撰稿人 Bryan Henderson 根据与上述相同的条款许可本文档。 他的作品的版权归 2001© 所有。

注释

[1]

对于吹毛求疵者,请参见 第 10.7 节

[2]

您可能将这种类型的磁盘称为“IDE”。 严格来说,IDE 是一个不正确的名称。 IDE 指的是“集成驱动器电子设备”技术,所有现代磁盘驱动器(包括所有 SCSI 磁盘驱动器)都使用该技术。 常见的第一个 IDE 驱动器是 ATA,名称有点混淆。 ATA 像 SCSI 一样,是对电气信号、命令等的精确规范。