内核模块

来自 ArchWiki
(重定向自 Blacklist

内核模块 是可以按需加载和卸载到内核中的代码片段。 它们扩展了内核的功能,而无需重启系统。

要创建内核模块,您可以阅读 Linux 内核模块编程指南。 模块可以配置为内置或可加载。 要动态加载或移除模块,它必须在内核配置中配置为可加载模块(因此与模块相关的行将显示字母 M)。

要在安装新内核时自动重建内核模块,请参阅 动态内核模块支持 (DKMS)。

获取信息

通常,模块依赖于内核版本,并存储在 /usr/lib/modules/kernel_release/ 目录中。

提示: 运行 uname -r (或 uname --kernel-release) 以获取您当前的内核版本。
注意: 模块和别名名称通常使用下划线 (_) 或破折号 (-);但是,当使用 modprobe 命令以及 /etc/modprobe.d/ 中的配置文件时,这些符号可以互换使用(会自动转换为下划线,请参阅 modprobe(8) § DESCRIPTIONmodprobe.d(5) § DESCRIPTION)。

显示当前加载的内核模块:

$ lsmod

显示有关模块的信息:

$ modinfo module_name

要列出为已加载模块设置的选项,请使用来自 sysfsutilssystool(1)

$ systool -v -m module_name

显示所有模块的综合配置:

$ modprobe -c | less

显示特定模块的配置:

$ modprobe -c | grep module_name

列出模块(或别名)的依赖项,包括模块本身:

$ modprobe --show-depends module_name

自动模块加载

如今,所有必要的模块加载都由 udev 自动处理,因此如果您不需要使用任何树外内核模块,则无需将应在启动时加载的模块放入任何配置文件中。 但是,在某些情况下,您可能希望在启动过程中加载额外的模块,或者将另一个模块列入黑名单,以使您的计算机正常运行。

早期模块加载

早期模块加载取决于使用的 initramfs 生成器

注意: initramfs 镜像可能不包含 /etc/modules-load.d/ 中要求的内核模块,它也可能缺少在该文件夹中设置的文件(请参阅 #systemd)。

systemd

内核模块可以显式列在 /etc/modules-load.d/ 下的文件中,以便 systemd 在启动期间加载它们。 每个配置文件的命名风格为 /etc/modules-load.d/程序.conf。 配置文件仅包含要加载的内核模块名称列表,以换行符分隔。 空行和第一个非空白字符为 #; 的行将被忽略。

/etc/modules-load.d/virtio-net.conf
# Load virtio_net.ko at boot
virtio_net

有关更多详细信息,请参阅 modules-load.d(5)

手动模块处理

内核模块由 kmod 软件包提供的工具处理,该软件包作为内核软件包的依赖项安装。 您可以手动使用这些工具。 加载模块:

# modprobe module_name
注意: 如果您已升级内核但尚未重启,modprobe 将失败,且不显示任何错误消息,并以代码 1 退出,因为路径 /usr/lib/modules/kernel_release/ 不再存在。 当 modprobe 无法确定是否是这种情况时,请手动检查此路径是否存在。

要通过文件名加载模块(即未安装在 /usr/lib/modules/kernel_release/ 目录中的模块),请使用以下任一方法:

# insmod file_name module_options
# modprobe file_name

要卸载—移除—模块,请使用以下任一方法:

# rmmod module_name
# modprobe -r module_name
# modprobe --remove module_name

设置模块选项

要将参数传递给内核模块,您可以手动使用 modprobe 传递它们,或者确保始终应用某些参数,方法是使用 modprobe 配置文件或使用 内核命令行。 如果模块内置于内核中,则必须使用内核命令行,其他方法将不起作用。

使用 modprobe

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

# modprobe module_name parameter_name=parameter_value

使用 modprobe.d

/etc/modprobe.d/ 目录中的配置文件可用于将模块设置传递给 udev,udev 将使用 modprobe 来管理系统启动期间的模块加载。 此目录中的文件可以具有任何名称,只要它们以 .conf 扩展名结尾即可。 文件名很重要,请参阅 modprobe.d(5) § CONFIGURATION DIRECTORIES AND PRECEDENCE。 显示有效配置:

$ systemd-analyze cat-config modprobe.d

语法是:

/etc/modprobe.d/file_name.conf
options module_name parameter_name=parameter_value
注意: 给定模块的所有选项必须在单行中定义。 具有相同模块名称的新 options 行将替换前一个。

多个模块参数用空格分隔,反过来,一个参数可以接收逗号分隔的值列表

/etc/modprobe.d/file_name.conf
options module_name param1=value1 param2=value2a,value2b …

例如:

/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

使用内核命令行

您还可以使用内核命令行将选项传递给模块。 这是内置于内核的模块的唯一有效选项。 对于所有常见的 启动引导器,以下语法是正确的:

module_name.parameter_name=parameter_value

例如:

thinkpad_acpi.fan_control=1

只需将其添加到启动引导器配置文件中的相应行,如 内核参数#启动引导器配置 中所述。

别名

别名是模块的备用名称。 例如: alias my-mod really_long_modulename 表示您可以使用 modprobe my-mod 而不是 modprobe really_long_modulename。 您还可以使用 shell 样式的通配符,因此 alias my-mod* really_long_modulename 表示 modprobe my-mod-something 具有相同的效果。 创建别名:

/etc/modprobe.d/myalias.conf
alias my-mod really_long_module_name

别名可以是内部的—包含在模块本身中。 内部别名通常用于 #自动模块加载,当应用程序需要它时,例如,当内核检测到新设备时。 查看模块内部别名:

$ modinfo --field=alias module_name

查看已配置和内部别名:

$ modprobe --showconfig | grep '\<module_name$'

黑名单

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

提示: 不要将黑名单作为一个通用术语与使用 blacklist 关键字作为黑名单的特定情况混淆。

某些模块作为 initramfs 的一部分加载。 mkinitcpio -M 将打印出所有自动检测到的模块:为了防止 initramfs 加载其中一些模块,请在 /etc/modprobe.d 下的 .conf 文件中将它们列入黑名单,它应在映像生成期间由 modconf hook 添加。 运行 mkinitcpio -v 将列出各种 hook(例如 filesystems hook、block hook 等)拉入的所有模块。 如果您的 HOOKS 数组中没有 modconf hook(例如,您已偏离默认配置),请记住将该 .conf 文件添加到 /etc/mkinitcpio.conf 中的 FILES 数组中,并且一旦您将模块列入黑名单,请重新生成 initramfs,然后重启。

使用 modprobe.d

alias

通过覆盖禁用别名。 例如,为了防止蓝牙模块自动加载,使用名为 off 的模块,该模块不存在:

/etc/modprobe.d/modprobe.conf
alias net-pf-31 off
注意: 别名覆盖可以阻止自动模块加载,但仍然允许通过另一个别名或模块名称自动和手动加载模块。

blacklist

要禁用给定模块的所有内部别名,请使用 blacklist 关键字。 例如,为了防止 pcspkr 模块在启动时加载以避免通过 PC 扬声器 发出声音:

/etc/modprobe.d/nobeep.conf
blacklist pcspkr
注意: blacklist 配置命令(因为它处理别名)与 alias 命令具有相同的缺点:可以阻止自动加载,但模块仍然可以手动加载,或者在另一个模块依赖于它时自动加载。

install

对于 #alias#blacklist 注意中描述的行为,有一个解决方法。 install 配置命令指示 modprobe 运行自定义命令,而不是像往常一样将模块插入内核,因此您可以模拟模块成功加载:

/etc/modprobe.d/blacklist.conf
install module_name /bin/true

您可以强制模块始终加载失败,使用 /bin/false:这将有效地阻止模块以及任何依赖于它的模块通过任何方式加载,并且可能会生成日志错误消息。

使用内核命令行

提示: 如果损坏的模块导致系统无法启动,这可能非常有用。

您还可以从 启动引导器 启动项配置中将模块列入黑名单。

只需将 module_blacklist=module_name_1,module_name_2,module_name_3 添加到您的内核命令行,如 内核参数#启动引导器配置 中所述。

注意
  • 当您将多个模块列入黑名单时,请注意它们仅用逗号分隔。 空格或任何其他内容都可能会破坏语法。
  • module_blacklist 将使内核完全拒绝加载模块。
  • 如果您只想阻止隐式加载,但可能稍后手动加载模块,则正确的参数是 modprobe.blacklist=module_name_1,module_name_2,module_name_3。 但是,这不会阻止启动期间的显式加载,例如通过 systemd 或其他模块。

命令行选项的另一个用例是禁用模块的硬件特定组件,而无需完全禁用模块。 例如,禁用麦克风,同时保留其他声音输出选项。 有关一些示例,请参阅 BBS#303475

故障排除

模块未加载

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

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

警告: 忽略内核模块的版本检查可能会导致内核崩溃或系统由于不兼容而表现出未定义的行为。 仅在极其谨慎的情况下使用 --force-vermagic

参见