如何加载、卸载 Linux 内核模块并将其列入黑名单
Linux 内核功能(例如对特定设备或文件系统的支持)以模块的形式组织,这些模块可以静态构建到内核中,也可以作为单独的“单元”构建,可以根据请求加载和卸载。现在所需的模块都是自动加载的,因此我们很少需要显式管理它们。然而,在某些情况下,我们可能需要执行此类操作。
在本教程中,我们学习如何检索有关内核模块的信息,如何使用 modprobe 实用程序在运行时加载或卸载模块,以及如何在启动时加载或将模块列入黑名单。
在本教程中您将学习:
如何列出已加载的内核模块
如何获取有关内核模块的信息
如何使用 modprobe 加载和卸载内核模块
如何在启动时自动加载模块或将其列入黑名单
列出加载的模块
要检索已加载的内核模块的列表,我们所要做的就是检查 /proc/modules
文件的内容。您可以在下面看到文件中条目的示例:
i915 3174400 42 - Live 0x0000000000000000
如您所见,文件的内容分为六列。第一列包含模块的名称(本例中为“i915”:它是添加对 Intel 集成显卡的支持的模块);在第二个中,模块的内存大小以字节为单位报告(3174400)。第三列包含当前加载的模块实例的数量,在本例中为 42。
某些模块的正常工作依赖于其他模块提供的功能:第四列用于报告模块依赖项。在我们作为示例的条目中,我们可以看到该模块没有依赖项:我们在列中只能看到“-”字符。第五列报告模块的当前状态,可以是以下状态之一:Live、正在加载或正在卸载。
最后,在第六列中,我们可以看到模块加载的内存地址。
为了避免直接读取 /proc/modules 文件的内容,我们可以使用 lsmod 实用程序,它提供了更具可读性且格式良好的输出,其中包括一个标头:
Module Size Used by
i915 3174400 42
检索有关模块的信息
要获取有关特定 Linux 内核模块的信息,我们可以使用另一个实用程序:modinfo
。该实用程序提供有关作为其参数传递的模块的信息。我们可以通过使用模块的路径或名称来引用模块;当我们执行后者时,会在 /lib/modules/
目录中搜索该模块,其中“
$ uname -r
要获取有关“i915”模块的信息,我们将运行:
$ modinfo i915
除此之外,在命令的输出中,我们可以看到模块文件名、其作者、许可证和依赖项。我们还可以看到可以传递给模块以调整其行为的参数列表,以及它们的简要说明:
parm: modeset:Use kernel modesetting [KMS] (0=disable, 1=on, -1=force vga console preference [default]) (int)
parm: enable_dc:Enable power-saving display C-states. (-1=auto [default]; 0=disable; 1=up to DC5; 2=up to DC6; 3=up to DC5 with DC3CO; 4=up to DC6 with DC3CO) (int)
parm: enable_fbc:Enable frame buffer compression for power savings (default: -1 (use per-chip default)) (int)
parm: lvds_channel_mode:Specify LVDS channel mode (0=probe BIOS [default], 1=single-channel, 2=dual-channel) (int)
parm: panel_use_ssc:Use Spread Spectrum Clock with panels [LVDS/eDP] (default: auto from VBT) (int)
parm: vbt_sdvo_panel_type:Override/Ignore selection of SDVO panel mode in the VBT (-2=ignore, -1=auto [default], index in VBT BIOS table) (int)
parm: reset:Attempt GPU resets (0=disabled, 1=full gpu reset, 2=engine reset [default]) (uint)
parm: vbt_firmware:Load VBT from specified file under /lib/firmware (charp)
parm: error_capture:Record the GPU state following a hang. This information in /sys/class/drm/card<N>/error is vital for triaging and debugging hangs. (bool)
parm: enable_hangcheck:Periodically check GPU activity for detecting hangs. WARNING: Disabling this can cause system wide hangs. (default: true) (bool)
parm: enable_psr:Enable PSR (0=disabled, 1=enable up to PSR1, 2=enable up to PSR2) Default: -1 (use per-chip default) (int)
parm: psr_safest_params:Replace PSR VBT parameters by the safest and not optimal ones. This is helpful to detect if PSR issues are related to bad values set in VBT. (0=use VBT p
arameters, 1=use safest parameters) (bool)
parm: enable_psr2_sel_fetch:Enable PSR2 selective fetch (0=disabled, 1=enabled) Default: 0 (bool)
parm: force_probe:Force probe the driver for specified devices. See CONFIG_DRM_I915_FORCE_PROBE for details. (charp)
parm: disable_power_well:Disable display power wells when possible (-1=auto [default], 0=power wells always on, 1=power wells disabled when possible) (int)
parm: enable_ips:Enable IPS (default: true) (int)
parm: fastboot:Try to skip unnecessary mode sets at boot time (0=disabled, 1=enabled) Default: -1 (use per-chip default) (int)
parm: load_detect_test:Force-enable the VGA load detect code for testing (default:false). For developers only. (bool)
parm: force_reset_modeset_test:Force a modeset during gpu reset for testing (default:false). For developers only. (bool)
parm: invert_brightness:Invert backlight brightness (-1 force normal, 0 machine defaults, 1 force inversion), please report PCI device ID, subsystem vendor and subsystem device I
D to dri-devel@lists.freedesktop.org, if your machine needs it. It will then be included in an upcoming module version. (int)
parm: disable_display:Disable display (default: false) (bool)
parm: memtest:Perform a read/write test of all device memory on module load (default: off) (bool)
parm: mmio_debug:Enable the MMIO debug code for the first N failures (default: off). This may negatively affect performance. (int)
parm: verbose_state_checks:Enable verbose logs (ie. WARN_ON()) in case of unexpected hw state conditions. (bool)
parm: nuclear_pageflip:Force enable atomic functionality on platforms that don't have full support yet. (bool)
parm: edp_vswing:Ignore/Override vswing pre-emph table selection from VBT (0=use value from vbt [default], 1=low power swing(200mV),2=default swing(400mV)) (int)
parm: enable_guc:Enable GuC load for GuC submission and/or HuC load. Required functionality can be selected using bitmask values. (-1=auto [default], 0=disable, 1=GuC submission,
2=HuC load) (int)
parm: guc_log_level:GuC firmware logging level. Requires GuC to be loaded. (-1=auto [default], 0=disable, 1..4=enable with verbosity min..max) (int)
parm: guc_firmware_path:GuC firmware path to use instead of the default one (charp)
parm: huc_firmware_path:HuC firmware path to use instead of the default one (charp)
parm: dmc_firmware_path:DMC firmware path to use instead of the default one (charp)
parm: enable_dp_mst:Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true) (bool)
parm: enable_dpcd_backlight:Enable support for DPCD backlight control(-1=use per-VBT LFP backlight type setting [default], 0=disabled, 1=enable, 2=force VESA interface, 3=force I
ntel interface) (int)
parm: enable_gvt:Enable support for Intel GVT-g graphics virtualization host support(default:false) (bool)
parm: request_timeout_ms:Default request/fence/batch buffer expiration timeout. (uint)
parm: lmem_size:Set the lmem size(in MiB) for each region. (default: 0, all memory) (uint)
parm: lmem_bar_size:Set the lmem bar size(in MiB). (uint)
parm: mitigations:Selectively enable security mitigations for all Intel® GPUs in the system.
如何将参数传递给模块?让我们来看看吧!
使用 modprobe 加载和卸载模块
要加载或卸载 Linux 内核模块,我们可以使用 modprobe 实用程序。 Modprobe 足够智能,可以解决模块依赖关系,因此当我们加载模块时,它的依赖关系也会被加载。该命令将我们要操作的模块的名称作为第一个参数。加载模块时,我们还可以指定应加载的以逗号分隔的参数列表。
加载模块
假设我们想要加载 i915 模块,显式启用详细状态检查。我们会运行:
$ sudo modprobe i915 verbose_state_checks=1
要将新参数应用于模块,我们应该首先卸载它(如果可能),或者更改 /sys/module/
$ sudo cat /sys/module/i915/parameters/verbose_state_checks
Y
在这种情况下,该功能已启用。假设我们想在不卸载模块的情况下禁用它,我们可以简单地将新值写入文件:
$ echo 0 | sudo tee /sys/module/i915/parameters/verbose_state_checks
请注意,并非所有参数都可以像上面那样更改。如果某个参数无法更改,则对应的文件将没有写权限。
卸载模块
要卸载一个或多个模块,我们仍然使用 modprobe,但我们使用 -r
选项运行它。如果我们尝试卸载当前正在使用的模块,我们会收到错误:
$ sudo modprobe -r i915
modprobe: FATAL: Module i915 is in use.
正如我们已经说过的,modprobe 是依赖感知的,因此当卸载模块时,它会尝试卸载它所依赖的所有模块(如果它们未使用)。
在启动时加载模块或将其列入黑名单
像我们在前面的示例中所做的那样使用 modprobe 加载模块不会使该模块在下次启动系统时自动加载。要使模块在启动时加载,我们必须将其名称附加到 /etc/modules
文件(如果不存在则创建它),或者附加到带有“.conf”的文件” 扩展名,位于 /etc/modules-load.d/
目录下。例如,为了在启动时加载假设的模块“foo”,我们可以在 /etc/modules-load.d/foo.conf
文件中写入“foo”:
$ echo "foo" | sudo tee /etc/modules-load.d/foo.conf
如果我们想指定模块在启动时加载的选项,或者阻止加载模块,我们应该在 /etc/modprobe.d< 下创建一个扩展名为“.conf”的文件/代码> 目录。例如,为了在不进行详细状态检查的情况下加载 i915 模块,我们将创建 /etc/modprobe.d/i915.conf
文件,其中包含以下内容:
options i915 verbose_state_checks=0
相反,要将模块列入黑名单,我们将使用“blacklist”指令:
blacklist i915
结论
Linux 功能以模块的形式组织,这些模块可以静态构建到内核中,也可以在需要时加载和卸载。在本教程中,我们了解了如何列出已加载的模块、获取有关它们的信息以及如何使用 modprobe 实用程序在运行时加载或卸载模块。我们还了解了如何在启动时自动加载模块(无论是否有特定选项),以及如何通过将其列入黑名单来防止模块被加载。