Linux如何选择加载哪些模块?

我正在使用Ubuntu 12.04.3 LTS操作系统。
uname -a
Linux guru 3.8.0-34-generic #49~precise1 [...] x86_64 [...]

当我重新启动时,我在系统日志中看到以下内容:
Dec 29 06:30:22 guru kernel: [...] e1000e: Intel PRO/1000 Network Driver - 2.1.4-k

然而:
cd /lib/modules/3.8.0-34-generic/kernel/drivers/net/ethernet/intel/e1000e
strings e1000e.ko | grep -i version
version=2.5.4-NAPI

modinfo e1000e给我相同的版本(2.5.4-NAPI

在启动时,我以为内核会遍历/lib/modules/{版本字符串}/kernel/drivers并加载所需的内容...

但显然我错了

在这个启动驱动器上存在另外两个版本的e1000e.ko:

/lib/modules/3.8.0-29-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
/lib/modules/3.8.0-33-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko

这两个都是2.1.4-k版本...内核是否以某种方式从这些旧位置获取模块?排除以下情况:
grep -r e1000e /etc/*
/etc/udev/rules.d/70-persistent-net.rules:# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:19.0 (e1000e)

换句话说,在/etc/modprobe.d/blacklist*或/etc/init/module-init-tools.conf等文件中没有提到这个模块。
我注意到: /lib/modules/3.8.0-34-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko曾经是版本2.1.4-k...但后来我根据http://www.intel.com/support/network/sb/CS-032514.html进行了升级并重新启动...这就是我现在的情况。
有没有办法查询当前运行的模块,询问它从磁盘的哪个位置加载?
--sk
Stuart Kendrick
1个回答

据我所知,modprobe 只加载与当前运行的内核版本相同的模块,即从:
/lib/modules/<kerne-version>/

modinfo 显示当前内核要运行的(实际上不是当前正在运行的)假定模块的完整路径。所以你不能依赖它。我正在使用 Ubuntu 14.04,例子:

$ modinfo e1000e
filename:       /lib/modules/3.13.0-38-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
version:        2.3.2-k
license:        GPL
description:    Intel(R) PRO/1000 Network Driver
author:         Intel Corporation, <linux.nics@intel.com>
srcversion:     FAFC167239309C03F11F440
alias:          pci:v00008086d000015A3sv*sd*bc*sc*i*
alias:          pci:v00008086d000015A2sv*sd*bc*sc*i*
alias:          pci:v00008086d000015A1sv*sd*bc*sc*i*
[...]
alias:          pci:v00008086d000010A4sv*sd*bc*sc*i*
alias:          pci:v00008086d0000105Fsv*sd*bc*sc*i*
alias:          pci:v00008086d0000105Esv*sd*bc*sc*i*
depends:        ptp
intree:         Y
vermagic:       3.13.0-38-generic SMP mod_unload modversions 
signer:         Magrathea: Glacier signing key
sig_key:        2A:DE:ED:EA:6C:BA:0B:95:A6:22:22:40:71:1F:49:C8:72:07:BB:F6
sig_hashalgo:   sha512
parm:           debug:Debug level (0=none,...,16=all) (int)
parm:           copybreak:Maximum size of packet that is copied to a new buffer on receive (uint)
parm:           TxIntDelay:Transmit Interrupt Delay (array of int)
parm:           TxAbsIntDelay:Transmit Absolute Interrupt Delay (array of int)
parm:           RxIntDelay:Receive Interrupt Delay (array of int)
parm:           RxAbsIntDelay:Receive Absolute Interrupt Delay (array of int)
parm:           InterruptThrottleRate:Interrupt Throttling Rate (array of int)
parm:           IntMode:Interrupt Mode (array of int)
parm:           SmartPowerDownEnable:Enable PHY smart power down (array of int)
parm:           KumeranLockLoss:Enable Kumeran lock loss workaround (array of int)
parm:           WriteProtectNVM:Write-protect NVM [WARNING: disabling this can lead to corrupted NVM] (array of int)
parm:           CrcStripping:Enable CRC Stripping, disable if your BMC needs the CRC (array of int)

如果它没有显示,请尝试使用以下命令:modinfo -n e1000emodinfo --filename e1000e
/lib/modules/3.13.0-38-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko

可以使用insmod按全路径加载特定模块。但这可能会有害并且可能损坏硬件。然而,在大多数情况下,内核会进行严格检查,引发一些错误,例如(注意3.13.0-37-generic成功加载)。
$ sudo insmod /lib/modules/3.11.0-24-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
insmod: ERROR: could not insert module /lib/modules/3.11.0-24-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko: Invalid module format
$ sudo insmod /lib/modules/3.13.0-30-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
insmod: ERROR: could not insert module /lib/modules/3.13.0-30-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko: Invalid module format
$ sudo insmod /lib/modules/3.13.0-36-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
insmod: ERROR: could not insert module /lib/modules/3.13.0-36-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko: Invalid parameters
$ sudo insmod /lib/modules/3.13.0-37-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
$ sudo rmmod /lib/modules/3.13.0-37-generic/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
$ sudo insmod /lib/modules/3.13.0-38-lowlatency/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
insmod: ERROR: could not insert module /lib/modules/3.13.0-38-lowlatency/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko: Invalid module format

我认为sysfs显示了实际加载的模块:

$ more /sys/module/e1000e/version 
2.3.2-k
$ more /sys/module/e1000e/srcversion 
FAFC167239309C03F11F440

我无法检查它,因为在我的情况下,3.13.0-37-generic3.13.0-38-generic具有相同的版本。
注意:
为了完整起见,动态加载的内核模块由dkms处理,从以下位置加载:
/var/lib/dkms/<driver-name>/<driver-last-version>/<kernel-version>/<kernel-arch>/module/