Kernel module (简体中文) - ArchWiki

Jump to content

相关文章

- Boot Debugging
- Kernels (简体中文)
- Kernel parameters (简体中文)

翻译状态：本文是 Kernel_modules 的翻译。上次翻译日期：2022-08-23。如果英文版本有所更改，则您可以帮助同步翻译。

内核模块是可以按需加载或卸载的内核代码，可以不重启系统就扩充内核的功能。

要创建内核模块，请阅读此指南。模块可以设置成内置或者可加载，要动态加载或删除模块，必须在内核配置中将其配置为可加载模块（因此与模块相关的行将显示字母 `M`）。

## 获取信息

模块保存在 `/lib/modules/kernel_release` (使用 `uname -r` 命令显示当前内核版本)。

注意： 模块名通常使用 (`_`) 或 `-` 连接，但是这些符号在 `modprobe` 命令和 `/etc/modprobe.d/` 配置文件中都是可以相互替换的。

显示当前装入的内核模块：

    $ lsmod

显示模块信息：

    $ modinfo module_name

显示所有模块的配置信息：

    $ modprobe -c | less

显示某个模块的配置信息：

    $ modprobe -c | grep module_name

显示一个装入模块使用的选项：

    $ systool -v -m module_name

显示模块的依赖关系：

    $ modprobe --show-depends module_name

## 自动加载模块

目前，所有必要模块的加载均由 udev 自动完成。所以，如果不需要使用任何额外的模块，就没有必要在任何配置文件中添加启动时加载的模块。但是，有些情况下可能需要在系统启动时加载某个额外的模块，或者将某个模块列入黑名单以便使系统正常运行。

### systemd

内核模块可以在`/etc/modules-load.d/` 下的文件中明确列出，以便 systemd 在引导过程中加载它们。 每个配置文件都以 `/etc/modules-load.d/program.conf`的样式命名。 配置文件仅包含要加载的内核模块名称列表，以换行符分隔。 空行和第一个非空白字符为`#`或`;`的行被忽略。

    /etc/modules-load.d/virtio-net.conf

    # Load virtio_net.ko at boot
    virtio_net

另见modules-load.d(5)。

### 早期模块加载

initramfs 映像可能不包含 `/etc/modules-load.d/` 中要求的内核模块，它也可能缺少在该文件夹中设置的文件。早期模块加载取决于使用的 initramfs 生成器：

- mkinitcpio: 参见 Mkinitcpio#MODULES
- dracut: 参见 Dracut#Early kernel module loading
- booster: 参见 Booster#Early module loading

## 手动模块处理

内核模块由 kmod 包提供的工具处理。您可以手动使用这些工具。

注意： 如果你已经升级了你的内核但还没有重新启动，modprobe 将失败并且没有错误消息并以代码 1 退出，因为路径 `/usr/lib/modules/$(uname -r)/` 不再存在。当 modprobe 无法确定是否存在这种情况时，请手动检查此路径是否存在。

要手动装入模块的话，执行:

    # modprobe module_name

按文件名加载模块:

    # insmod filename [args]

如果要移除一个模块：

    # modprobe -r module_name

或者:

    # rmmod module_name

## 配置模块参数

要将参数传递给内核模块，您可以使用 modprobe 手动传递它们，或者使用 modprobe 配置文件或使用内核命令行确保始终应用某些参数。

### 手动加载时设置

将参数传递给模块的基本方法是使用 modprobe 命令。使用简单的 `key=value` 赋值在命令行上指定参数：

    # modprobe module_name parameter_name=parameter_value

### 使用 /etc/modprobe.d/中的文件

`/etc/modprobe.d/` 目录中的文件可用于将模块设置传递给 udev，它将使用 `modprobe` 管理系统启动期间的模块加载.此目录中的配置文件可以具有任何名称，只要它们以 .conf 扩展名结尾。语法是：

    /etc/modprobe.d/myfilename.conf

    options module_name parameter_name=parameter_value

例如：

    /etc/modprobe.d/thinkfan.conf

    # On ThinkPads, this lets the 'thinkfan' daemon control fan speed
    options thinkpad_acpi fan_control=1

注意： 如果任何受影响的模块是从 initramfs 加载的，那么您需要将适当的 .conf 文件添加到 mkinitcpio.conf 中的 `FILES` 或使用`modconf` hook，然后 重新生成 initramfs 以包含“.conf”文件。要查看默认 initramfs 的内容，请使用 lsinitcpio。

### 使用内核命令行

如果模块内置在内核中，您还可以使用内核命令行将选项传递给模块。对于所有常见的引导加载程序，请用以下语法：

    modname.parametername=parametercontents

例如:

    thinkpad_acpi.fan_control=1

只需将其添加到引导加载程序的内核行，如 内核参数 中所述。

## 别名

别名是模块的替代名称。例如：`alias my-mod real_long_modulename` 表示您可以使用 `modprobe my-mod` 代替 `modprobe real_long_modulename`。您也可以使用 shell 风格的通配符，所以 `alias my-mod* really_long_modulename` 和 `modprobe my-mod-something` 有相同的效果。创建别名：

    /etc/modprobe.d/myalias.conf

    alias mymod really_long_module_name

一些模块具有别名，用于在应用程序需要它们时自动加载它们。禁用这些别名可以防止自动加载，但仍允许手动加载模块。

    /etc/modprobe.d/modprobe.conf

    # Prevent Bluetooth autoload
    alias net-pf-31 off

## 黑名单

在内核模块的上下文中，黑名单是一种防止内核模块加载的机制。如果不需要相关的硬件，或者如果加载该模块会导致问题，这可能很有用：例如，可能有两个内核模块试图控制同一个硬件，将它们一起加载会导致冲突。

一些模块作为 initramfs 的一部分加载。 `mkinitcpio -M` 将打印出所有自动检测到的模块：为了防止 initramfs 加载其中一些模块，请将它们列入黑名单中的 `/etc/modprobe.d 下的 .conf 文件` 并且它应该在图像生成期间由 `modconf` 挂钩添加。运行 `mkinitcpio -v` 将列出由各种挂钩（例如 `filesystems` 挂钩、`block` 挂钩等）拉入的所有模块。如果您的文件中没有 `modconf` 挂钩，请记住将该 .conf 文件添加到 `/etc/mkinitcpio.conf` 中的 `FILES` 列表中`HOOKS` 列表（比如您改变了默认配置），将模块列入黑名单 regenerate the initramfs，然后重新启动。

### 使用 /etc/modprobe.d/ 中的文件

在 `/etc/modprobe.d/` 中创建一个 .conf 文件，并使用 `blacklist` 关键字为要列入黑名单的每个模块附加一行。例如，如果您想阻止 `pcspkr` 模块加载以避免通过 电脑扬声器 发出声音：

    /etc/modprobe.d/nobeep.conf

    # Do not load the 'pcspkr' module on boot.
    blacklist pcspkr

Note: `blacklist` 命令将一个模块列入黑名单，这样它就不会自动加载，但如果另一个未列入黑名单的模块依赖于它或者它是手动加载的，则该模块可能会被加载。

但是，对于该情况有一个解决方法； `install` 命令指示 modprobe 运行自定义命令，而不是像往常一样将模块插入内核，因此您可以强制使模块加载失败：

    /etc/modprobe.d/blacklist.conf

    ...
    install module_name /bin/true
    ...

这将有效地将该模块和任何其他依赖于它的模块列入黑名单。

### 使用内核命令行

提示： 如果模块损坏导致无法引导系统，这将非常有用。

您也可以从引导加载程序中将模块列入黑名单。

如Kernel参数.中所述，只需将`module_blacklist=modname1,modname2,modname3` 添加到引导加载程序的内核行中即可。

注意： 将多个模块列入黑名单时，请注意，它们之间仅用逗号分隔。 空格或其他内容可能会破坏语法。

## 问题处理

### 模块未加载

如果特定模块未加载并且启动日志（可通过以 root 身份运行 `journalctl -b` 访问）显示该模块已列入黑名单，但目录 `/etc/modprobe.d/` 没有显示相应的条目，请检查 `/usr/lib/modprobe.d/` 的另一个 modprobe 源目录以获取黑名单条目。

如果内核模块中包含的“vermagic”字符串与当前运行的内核的值不匹配，则不会加载模块。如果已知模块与当前运行的内核兼容，则可以使用 `modprobe --force-vermagic` 忽略“vermagic”检查。

警告： 忽略内核模块的版本检查可能会导致内核崩溃或系统由于不兼容而表现出未定义的错误。请谨慎使用 `--force-vermagic`。

## 参见

- 禁用 PC喇叭
- 编写 WMI 驱动程序 - 一个 LWM 介绍

Categories:

- Kernel (简体中文)
- Hardware detection and troubleshooting (简体中文)