浅析Linux内核模块自加载机制

文章目录

    • 概述
    • Linux内核模块管理
      • 内核模块存放目录
        • modules系列文件
      • 阻止模块启动时加载
    • systemd-module-load.service
      • 配置文件
      • 内核启动参数
    • udev动态加载机制
      • udev工作流程
      • udev配置示例:网卡重命名
    • 相关参考

概述

模块自加载用于配置系统在启动时自动加载所需要的模块,这在添加新的设备和驱动很有用。Linux系统中可以实现模块自加载的机制通常有两种方式:

  • 方式1:基于systemd提供的modules-load服务,使用静态配置。
  • 方式2:基于udev的动态加载机制。

Linux内核模块管理

在进一步说明上述机制前,对于Linux内核模块的管理需要有个基本的了解,内核模块所暴露的信息,是这两种机制正确加载模块所必不可少的一部分。

内核模块存放目录

所有的内核模块默认都会安装到在/lib/modules/uname -r路径下,通常包含的内容如下:
浅析Linux内核模块自加载机制_第1张图片
先看该路径下包含的目录信息,这些目录按照类别存放了不同的内核模块:

  • kernel:用于存放Linux源码中包含的内核模块;
  • extra:存放外部的内核模块
  • weak-updates:存放与当前安装内核kABI兼容的内核模块;
  • updates:NA
  • vdso:NA
modules系列文件

除了存放内核模块的目录外,/lib/modules/uname -r路径下还包含了一系列以modules开头的文件,这些文件描述内核模块的一些关键信息,例如模块命名、依赖关系、导出符号等。

  • modules.alias:记录模块的命名;
  • modules.dep:记录模块间的依赖关系,在使用modprobe加载模块时,会根据该文件查找依赖的内核模块;
  • modules.order:记录模块的加载顺序;
  • modules.symbols:记录模块导出的外部符号。

其它modules.*文件则保存了某一子系统的内核模块列表,比如modules.block就保存了块设备相关的模块,modules.builtin保存了编译进内核的模块。

阻止模块启动时加载

如果想要阻止一个内核模块在系统启动时加载,在文件夹/etc/modprobe.d目录下创建一个.conf文件,通过blacklist来屏蔽模块的自动加载,如下:

blacklist module_name

systemd-module-load.service

目前,所有必要模块的加载均由udev自动完成,但是,有些情况下可能需要在系统启动时加载某个额外的模块,这时就可以使用systemd-module-load.service。systemd-modules-load.service是systemd提供的一个开机自启动服务,用于在系统启动时根据静态的配置文件或者内核启动参数加载内核模块。
浅析Linux内核模块自加载机制_第2张图片

配置文件

systemd-modules-load.service支持识别以下目录中的配置文件:

  • /etc/modules-load.d/*.conf
  • /run/modules-load.d/*.conf
  • /lib/modules-load.d/*.conf
  • /usr/lib/modules-load.d/*.conf
  • /usr/local/lib/modules-load.d/*.conf

systemd-modules-load.service从上述目录中读取 *.conf 文件,这些 *.conf 文件中静态的包含了需要在系统启动时无条件加载的内核模块列表。

内核启动参数

除了配置文件,systemd-modules-load.service还支持识别以下的内核引导选项:

modules_load=, rd.modules_load=

上述选项通过接受一个内核模块列表,表示在系统启动的早期,无条件的加载这些内核模块。以 “rd.” 作为前缀的选项仅作用于 initial RAM disk 环境。

udev动态加载机制

udev是使用uevent机制来处理设备热插拔事件的用户空间程序,并取代原来的devfs机制。动态管理设备和驱动的加卸载是udev的基础功能。

udev工作流程

udev使用netlink机制与内核进行通信,它在系统启动时运行了一个后台程序udevd,监听内核发送的uevent事件,并通过一套规则匹配可发现的设备事件和属性,来执行相应的热拔插动作,支持创建/删除设备节点、加载/卸载驱动模块等。

浅析Linux内核模块自加载机制_第3张图片

udev配置示例:网卡重命名

对于多网卡命名需要在/etc/udev/rules.d/70-persistent-net.rules文件中,定义多条定义规则。

SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="24:6e:96:03:5c:8d", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="24:6e:96:03:5c:8a", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="24:6e:96:03:5c:8c", ATTR{type}=="1", KERNEL=="eth*", NAME="eth2"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="52:54:00:58:0e:01", ATTR{type}=="1", KERNEL=="eth*", NAME="eth3"

相关参考

  • modules-load.d 中文手册
  • Linux设备驱动模块自加载示例与原理解析
  • depmod (生成内核、模块、依赖关系列表和关联的映射文件)
  • udev高效、动态地管理 Linux 设备文件

你可能感兴趣的:(Linux系统管理,linux,java,网络)