我想知道Linux(例如我们的Ubuntu)在从头开始安装时如何“知道”如何安装以及安装哪些驱动程序。例如,我买了一台没有任何系统的新电脑,我安装了Ubuntu。我的 PC 内部有 GPU、HDD 等,还有一些外围设备,如鼠标、键盘等。显然,全新安装没有系统控制硬件并与硬件通信所需的驱动程序,那么 Ubuntu 如何“知道” “要安装/下载哪些驱动程序以及它是如何做到的?
答案1
(基于 Google 缓存的副本http://people.skolelinux.org/pere/blog/Modalias_strings___a_practical_way_to_map__stuff__to_hardware.html作者:彼得·莱因霍德森。)
在硬件中,只要您知道特定 I/O 总线或子系统的标准访问方法,就可以访问某些标准设备标识符,而无需进一步了解实际设备。在Linux中,这些标识符用于构建模态字符串,然后用于查找每个设备的正确驱动程序。
每个驱动程序模块的源代码可以包括MODULE_DEVICE_TABLE
结构,命令使用这些结构depmod
来创建模块别名通配符条目,该条目将与该特定模块支持的硬件的模态字符串相匹配。
当内核检测到某个硬件尚未加载匹配的驱动程序时,它将根据硬件的标识符创建一个模态字符串,并使用它来请求自动加载模块。然后该modprobe
命令将使用/lib/modules/$(uname -r)/modules.alias[.bin]
创建的文件depmod
来查看是否存在匹配的模块。如果是,则加载该模块并在必要时探测硬件以获取更多详细信息。
例如,我有一个 DVB 电视卡:
$ lspci -v -nn -s 07:00.0
07:00.0 Multimedia video controller [0400]: Conexant Systems, Inc. CX23885 PCI Video and Audio Decoder [14f1:8852] (rev 04)
Subsystem: Hauppauge computer works Inc. CX23885 PCI Video and Audio Decoder [0070:6a28]
这会产生如下的模态字符串:
pci:v000014F1d00008852sv00000070sd00006A28bc04sc00i00
该模块在其源代码中cx23885
具有以下别名:MODULE_DEVICE_TABLE
# modinfo cx23885
...
alias: pci:v000014F1d00008880sv*sd*bc*sc*i*
alias: pci:v000014F1d00008852sv*sd*bc*sc*i*
...
当内核检测到该卡时,它会有效地运行该modprobe pci:v000014F1d00008852sv00000070sd00006A28bc04sc00i00
命令。模块的第二个别名cx23885
匹配,因此该模块被加载。
PCI/PCI-X/PCIe 总线设备
这是“PCI 子类型”。它使用像这样的模态字符串:
pci:v00008086d00002770sv00001028sd000001ADbc06sc00i00
可以如下解码:
v 00008086 (vendor)
d 00002770 (device)
sv 00001028 (subvendor)
sd 000001AD (subdevice)
bc 06 (bus class)
sc 00 (bus subclass)
i 00 (interface)
使用lspci -nn
,您可以查看类、子类、供应商和设备 ID。如果添加该-v
选项,您还可以看到子供应商:子设备 ID。
USB设备
对于 USB 设备,模态字符串如下所示:
usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00
这将解压为:
v 1D6B (device vendor)
p 0001 (device product)
d 0206 (bcddevice)
dc 09 (device class)
dsc 00 (device subclass)
dp 00 (device protocol)
ic 09 (interface class)
isc 00 (interface subclass)
ip 00 (interface protocol)
使用该lsusb
命令,您可以查看供应商和产品 ID。如果您使用该-v
选项,您也可以看到其他 ID。
ACPI 设备
它们使用 ACPI PNP 标识符,以冒号为前缀acpi:
并以冒号分隔:
acpi:IBM0071:PNP0511:
DMI 设备
这可能是一个很长的模态字符串:
dmi:bvnIBM:bvr1UETB6WW(1.66):bd06/15/2005:svnIBM:pn2371H4G:pvrThinkPadX40:rvnIBM:rn2371H4G:rvrNotAvailable:cvnIBM:ct10:cvrNotAvailable:
这将解压为:
bvn IBM (BIOS vendor)
bvr 1UETB6WW(1.66) (BIOS version)
bd 06/15/2005 (BIOS date)
svn IBM (system vendor)
pn 2371H4G (product name)
pvr ThinkPadX40 (product version)
rvn IBM (board vendor)
rn 2371H4G (board name)
rvr NotAvailable (board version)
cvn IBM (chassis vendor)
ct 10 (chassis type)
cvr NotAvailable (chassis version)
SerIO 设备,即主要是 PS/2 鼠标
模态字符串将如下所示:
serio:ty01pr00id00ex00
这里的值是:
ty 01 (type)
pr 00 (prototype)
id 00 (id)
ex 00 (extra)
其他总线/设备类型
Linux 内核还可以识别许多其他总线类型。研究内核源文件的内容文件2别名.c可能有助于破译每种类型的模态字符串的组成部分的含义。
答案2
所有外围设备都通过大多唯一的 ID 来标识自己。有些 ID 用于通用接口(HDD/鼠标等)。 Linux 内置了大多数驱动程序,并且通用驱动程序具有支持有限功能集的 ID 的兼容性列表。它变得更加复杂,但 dmesg、lscpu、hwinfo、lshw、dmidecode、lspci 等将列出 ID(如果您想查看)