Answers:
尽管其中很多确实在引导过程中最终被加载,但它们不会在启动时或其他任何时间自动加载。发生这种情况有三种不同的机制:
用户空间请求:涵盖从初始化服务到udev到命令行的所有内容。如果要在引导时加载特定的模块,init或udev可能是最直接的方法。
热插拔设备:当您将某物连接到USB或PCI时,内核会检测到此情况,并根据设备如何标识自身来请求适当的模块。
所需的协议或其他实现:当内核需要执行某些操作(例如读取文件系统)并发现其缺乏执行该操作的知识时,它将请求一个模块。
请注意,对于最后两个,我使用了短语“请求模块”-这是因为内核实际上是通过kmod
执行的用户空间守护程序加载的/sbin/modprobe
。根据Linux Kernel Architecture中的 Wolfgang Mauerer所述,在2.6内核中只有约100个不同的点可以调用内部request_module()
函数。
modprobe
使用已安装的MODULE_ALIAS的数据库。这些是在模块源代码中显式指定的,或者是从模块源代码MODULE_DEVICE_TABLE派生的,该模块是模块服务的OEM设备ID的列表。
许多系统都设置为使用initrd或initramfs。这些是引导加载程序加载的文件系统映像,在内核安装根分区之前可用于内核。这样就可以将安装根分区所需的驱动程序(磁盘驱动程序,文件系统驱动程序,设备映射器或逻辑卷驱动程序等)编译为模块并从initrd / initramfs加载。
initrd(/linuxrc
)或initramfs(/init
)上的启动脚本通常会加载一些模块并找到根文件系统。每个发行版都有自己的设置。Ubuntu使用initramfs,该initramfs由initramfs-tools
软件包中的组件组装而成,并根据安装根文件系统所需的驱动程序为每个内核重新生成。
挂载根文件系统后,在系统引导过程中,将加载/etc/modules
(Debian,…)或/etc/modules.conf
(Red Hat,Arch,…)中列出的模块。该文件通常列出几个模块(如果有)。大多数模块按需加载。
当内核检测到某些缺少驱动程序的硬件或某些其他组件(例如网络协议或密码算法)时,它将调用/sbin/modprobe
以加载模块。对于硬件驱动程序,内核传递的名称会编码PCI ID,USB ID或其他硬件的系统名称。表格中将/lib/modules/$VERSION/modules.alias
这些系统名称映射到模块名称。该表由生成并由depmod
读取modprobe
。
如果您有一个为硬件设备手动编译的额外内核模块,请将其放入/lib/modules/$VERSION/local
(local
如果不存在则创建子目录)并运行depmod -a
以重新生成别名数据库。如果该模块具有内核无法自动检测到的某些异常功能,请将其放入/lib/modules/$VERSION/local
,运行depmod -a
以分析其依赖性,然后将模块名称添加到中/etc/modules
。
/lib/modules/…
。只需创建local
子目录(递归depmod
遍历/lib/module/$VERSION
)。
/var/lib/modules
或/lib/modules/*/local
,也找不到任何提及depmod
。在CentOS 6.4、7.4和Ubuntu 19.04中查看。