lspci 收集信息的常用命令
lspci -tv
lspci -xxx
lspci -vvv
lspci -tv
[longyu@debian-10:08:24:24] tmp $ lspci -tv
-[0000:00]-+-00.0 Intel Corporation Device 3e34
+-02.0 Intel Corporation UHD Graphics 620 (Whiskey Lake)
+-04.0 Intel Corporation Skylake Processor Thermal Subsystem
+-12.0 Intel Corporation Cannon Point-LP Thermal Controller
+-14.0 Intel Corporation Cannon Point-LP USB 3.1 xHCI Controller
+-14.2 Intel Corporation Cannon Point-LP Shared SRAM
+-14.3 Intel Corporation Cannon Point-LP CNVi [Wireless-AC]
+-14.5 Intel Corporation Device 9df5
+-15.0 Intel Corporation Device 9de8
+-15.1 Intel Corporation Device 9de9
+-16.0 Intel Corporation Cannon Point-LP MEI Controller
+-17.0 Intel Corporation Cannon Point-LP SATA Controller [AHCI Mode]
+-1d.0-[01]----00.0 Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
+-1d.4-[02]----00.0 Sandisk Corp WD Black 2018/PC SN520 NVMe SSD
+-1f.0 Intel Corporation Cannon Point-LP LPC Controller
+-1f.3 Intel Corporation Cannon Point-LP High Definition Audio Controller
+-1f.4 Intel Corporation Cannon Point-LP SMBus Controller
\-1f.5 Intel Corporation Cannon Point-LP SPI Controller
此命令输出 pci 结构简略树状图。
lspci -xxx
[longyu@debian-10:08:25:51] tmp $ lspci -xxx
00:00.0 Host bridge: Intel Corporation Device 3e34 (rev 0b)
00: 86 80 34 3e 06 00 90 20 0b 00 00 06 00 00 00 00
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 3c 10 a5 85
30: 00 00 00 00 e0 00 00 00 00 00 00 00 00 00 00 00
此命令输出 16 进制形式显示的 pci 配置空间 dump 数据。
lspci -vvv
[root@debian-10:08:26:12] tmp # lspci -vvv
00:00.0 Host bridge: Intel Corporation Device 3e34 (rev 0b)
Subsystem: Hewlett-Packard Company Device 85a5
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort+ >SERR- <PERR- INTx-
Latency: 0
Capabilities: [e0] Vendor Specific Information: Len=10 <?>
.........
此命令显示详细的 pci 信息,这些信息都是通过读取 pci 设备在 /sys 目录下的 config 配置完成的。
lspci 命令的原理
1. 扫描 /sys/bus/pci/devices/ 目录,获取每个 pci 设备信息
................
152 openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:17.0/irq", O_RDONLY) = 4
153 read(4, "127\n", 1024) = 4
154 close(4) = 0
155 openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:17.0/vendor", O_RDONLY) = 4
156 read(4, "0x8086\n", 1024) = 7
157 close(4) = 0
158 openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:17.0/device", O_RDONLY) = 4
159 read(4, "0x9dd3\n", 1024) = 7
160 close(4) = 0
161 openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:17.0/class", O_RDONLY) = 4
162 read(4, "0x010601\n", 1024) = 9
163 close(4) = 0
164 openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:15.1/resource", O_RDONLY) = 4
165 fstat(4, {st_mode=S_IFREG|0444, st_size=4096, ...}) = 0
166 read(4, "0x000000400010f000 0x00000040001"..., 4096) = 741
..............
读取了如下几个文件内容:
- irq
- vendor
- device
- class
- resource
lspci 执行过程中对上述五种文件内容外加 config 文件内容首先读取然后格式化输出。
2. 读取每个 pci 设备的 config 文件,处理后输出
lspci 的一些显示依赖 pci 设备配置空间的内容,这通过读取 /sys/bus/pci/device/ pci 设备子目录中的 config 文件来完成,示例过程如下:
.............
470 openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:1f.4/config", O_RDONLY) = 3
471 pread64(3, "\206\200\243\235\3\0\200\2\21\0\5\f\0\0\0\0\4\300\20\0@\0\0\0\0\0\0\0\0\0\0\0"..., 64, 0) = 64
472 close(3) = 0
473 openat(AT_FDCWD, "/sys/bus/pci/devices/0000:00:14.0/config", O_RDONLY) = 3
474 pread64(3, "\206\200\355\235\6\4\220\2\0210\3\f\0\0\200\0\4\0 \301\0\0\0\0\0\0\0\0\0\0\0\0"..., 64, 0) = 64
475 close(3) = 0
....................
3. 使用 vendor id 与 device id 检索数据库以获取 pci 设备对应的英文名称字符串
lspci 执行时一般会显示用户易理解的字符串来表示设备的类型,示例内容如下:
00:00.0 Host bridge: Intel Corporation Device 3e34 (rev 0b)
00:02.0 VGA compatible controller: Intel Corporation UHD Graphics 620 (Whiskey Lake)
这些字符串与 vendor id 及 device id 的对应关系默认在 /usr/share/pci.ids.gz 中存放,lspci 需要解压此文件,然后通过 pci 的 vendor id 与 device id 在其中匹配,匹配到后则输出用户易理解的字符串描述 pci 设备。
当 /usr/share/pci.ids.gz 不存在时 lspci 依次尝试如下文件:
- /usr/share/misc/pci.ids
- /home/xxx/.pciids-cache
- 不同目录中的 hwdb.bin 文件
示例过程如下:
openat(AT_FDCWD, "/usr/share/misc/pci.ids.gz", O_RDONLY) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/share/misc/pci.ids", O_RDONLY) = 4
openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/etc/passwd", O_RDONLY|O_CLOEXEC) = 4
openat(AT_FDCWD, "/home/longyu/.pciids-cache", O_RDONLY) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/etc/systemd/hwdb/hwdb.bin", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/etc/udev/hwdb.bin", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/lib/systemd/hwdb/hwdb.bin", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/lib/systemd/hwdb/hwdb.bin", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/lib/udev/hwdb.bin", O_RDONLY|O_CLOEXEC) = 4