lspci 命令详解:从 PCI 设备识别到驱动排查实战
发布时间:2026/10/22 7:49:06 锦皓数字建站

排查一台机器认不到网卡我习惯性敲下lspci | grep -i ethernet看到输出里有一行以太网控制器悬着的心就放下了一半。lspci 作为 Linux 下查看 PCI 总线信息的基础命令几乎每个发行版都自带但真正把它用顺手的人其实不多。这篇文章打算把它拆开讲透从输出含义、参数组合到实战排查思路覆盖日常运维、驱动开发、虚拟化直通这些常见场景。适合刚接触 Linux 的初学者也适合天天跟服务器和硬件打交道的工程师读完你会发现很多“凭感觉”的操作其实可以变成一套标准动作。1. 为什么系统管理员都离不开 lspci先说清它在 Linux 生态里的定位1.1 PCI 总线不是什么“总线”而是主机与外部设备之间的骨架很多人把 PCI 理解成一根线设备挂在这根线上这个理解不太准确。PCI/PCIe 体系更像是城市的交通网络CPU 和内存是市中心显卡、网卡、NVMe 盘这些设备是各个功能区中间由大量“桥”Bridge连接起来每座桥负责一段区域的路由和转发。主板上的设备并不是随便摆在某个地址上而是挂在一条条 PCIe 链路上。CPU 要访问网卡的寄存器、要读写 GPU 的显存、要给 NVMe 盘发命令靠的都是这些链路。lspci 干的事就是把这个庞大的交通网络“拍一张全景照片”哪条链路接了哪些设备、设备是什么类型、设备的厂商和设备 ID 是多少、用了哪个内核驱动全都枚举出来。所以 lspci 显示的其实不只是“PCI 总线信息”而是当前主机完整的设备树骨架。没有它很多排查工作就像在黑灯瞎火里找东西。1.2 lspci 一秒钟读懂了什么BDF 地址、设备类别、厂商 ID先随便看一行真实输出简化示意实际厂商名会显示具体芯片商名称我这里统一处理成“某厂商”01:00.0 VGA compatible controller [0300]: 某厂商显卡设备 [10de:xxxx] (rev a1)这一行拆开看信息密度非常高。开头的01:00.0就是 PCI 设备的“门牌号”按“总线号:设备号.功能号”的格式BDFBus:Device.Function。总线号是 8bit范围 0 到 255设备号是 5bit范围 0 到 31功能号是 3bit范围 0 到 7。一个物理 PCIe 设备可以拆成最多 8 个功能每个功能在软件看来都是一个独立的 PCI 设备有自己的配置空间。紧接着的VGA compatible controller是设备类别。PCI 规范把设备按功能分成大类比如 0x03 是显示控制器、0x02 是网络控制器、0x01 是存储控制器、0x06 是桥设备。lspci 会把这个分类代码翻译成人类可读的文字。中括号里的[0300]是类别代码的数字形式再后面的[10de:xxxx]是厂商 ID 和设备 ID。厂商 ID 全球唯一由 PCI 组织分配设备 ID 由厂商自己定义。这两个 ID 是驱动匹配的核心依据后面排查驱动问题时会反复用到。1.3 为什么说“ID 比文字名称更可靠”lspci 输出的设备名称是 pci.ids 数据库根据厂商 ID 和设备 ID 查出来的。如果数据库版本太老或者设备太新名称就会显示成Unknown device或者干脆只有一堆数字。这时候不要慌看数字反而更准——lspci -nn会把厂商和设备 ID 直接印在方括号里拿着这个 ID 去查驱动或者查硬件规格比看文字靠谱得多。我见过有人对着lspci里一行Network controller [0280]犯迷糊因为系统没装无线网卡驱动名字已经显示不全了但加上-nn之后厂商 ID 和型号 ID 一目了然顺着 ID 找到对应驱动源码问题当场就解决了。2. 参数速查从 -v 到 -vvv每一级详细度到底多了什么2.1 最常用的几个筛选参数-s、-d、-n、-nn不带参数的 lspci 输出所有设备机器设备一多就开始眼晕。筛选参数是最实用的第一梯队。-s按 BDF 地址筛选用法是lspci -s 01:00.0。这个参数在需要精确锁定某个设备时特别好用比如刚定位到显卡在01:00.0后面所有详细查询都带上-s 01:00.0输出干干净净不会混进无关设备。-d按厂商 ID 或设备 ID 筛选格式是[厂商ID]:[设备ID]两边都可以留空。比如想看某个显卡厂商的设备lspci -d 10de:直接过滤出该厂商全部设备如果知道具体设备号想精确定位lspci -d 10de:1e07也能做到。这个参数在机器上插了多张同类设备时非常方便。-n和-nn控制数字 ID 的显示。-n只显示数字不显示文字名称-nn在文字后面带上数字。日常排查我基本直接用-nn因为既能看懂类别又能拿到硬件 ID。比如写驱动加载脚本时经常用lspci -nn | grep -i ethernet拿到带 ID 的那一行再提取厂商和设备号做自动化判断。2.2 详细度三兄弟-v、-vv、-vvv 的差别在哪这三个参数是 lspci 的“扩音器”每加一个 v输出的信息就要翻好几倍。我第一次敲lspci -vvv的时候直接被输出长度吓到了一屏根本放不下。参数输出内容级别典型用途-v基础详细BAR 地址、中断、子系统 ID日常快速查看设备配置和驱动状态-vv增加 PCIe 能力、电源管理、链路协商状态检查 PCIe 速率/宽度、链路是否降级-vvv完整的配置空间和所有扩展能力驱动开发、固件调试、深挖硬件行为拿实际场景说lspci -v里能看到Kernel driver in use这一行判断驱动有没有绑定这个功能已经覆盖了 80% 的排查需求。lspci -vv则会在设备支持 PCIe 能力时输出LnkCap和LnkSta两个关键字段分别表示链路最大能力和当前协商状态新版工具还会显示LnkSta2里的实际解压速率。这些内容是判断“盘为什么只有一半速度”这类问题的核心依据。-vvv平时用得少但遇到疑难杂症会非常有用。设备能力列表、扩展能力项、配置空间的原始信息都会打出来跟调试工具的输出对照看往往能定位到具体是哪个能力位没被正确解析。2.3 树形视图和内核驱动-t 与 -k 的组合拳-t把 PCI 设备按拓扑画成树形结构顶层是 Root Port根端口下面挂桥桥下面再挂设备。这个参数在理解整机拓扑时很好用配合-v或者-k能让信息量更足所以我经常用lspci -tv或lspci -t先看整体。-k是显示内核驱动信息的专用参数等价于在详细输出里直接看Kernel driver in use和Kernel modules这两行。Kernel driver in use表示当前真正绑定到这个设备的驱动Kernel modules列出内核里哪些模块可以驱动它。这个参数属于高频中的高频排查设备没驱动、驱动绑错、设备被 vfio 接管这类问题基本第一反应就是lspci -nnk。要注意的是-k在部分旧版 pciutils 上单独使用不生效需要配合-v或-nn才能看到。如果是老系统建议直接lspci -nnk既拿到 ID 又拿到驱动状态一行命令解决大部分问题。3. 实战拆解三个高频场景命令一行行敲给你看3.1 场景一机器点不亮/显卡没驱动怎么用 lspci 定位遇到过一台机器独显怎么都加载不了驱动进系统后分辨率惨不忍睹。我的第一步永远是lspci -nnk | grep -iA3 vga输出大概是01:00.0 VGA compatible controller [0300]: 某显卡厂商设备 [10de:xxxx] (rev a1) Subsystem: 某设备厂商 Subsystem [xxxx:xxxx] Kernel driver in use: unknown Kernel modules: nvidiafb, nouveau看到Kernel driver in use: unknown基本可以确定驱动没装上。再看Kernel modules列出的是开源驱动模块而不是自己想要的闭源驱动就知道问题大概率在驱动安装环节而不是硬件没被识别。如果这块板卡本身是核心显卡和独立显卡双切换的机型还要注意lspci | grep -i vga到底列出了几行。只有一行即使亮着屏幕也可能是 CPU 核显在工作独显根本没被系统看到。这时候要去 BIOS 里确认显卡优先级和 PCIe 槽位开关lspci 只是个侦察兵报告完“设备不见了”之后剩下的排查该去固件设置里挖。3.2 场景二新装的 NVMe 盘速度不对先看链路协商有个朋友新装的 SSD 标称 3500MB/s实测只有一半。这种问题很多人第一反应是换线、换接口其实先用 lspci 看一眼链路协商状态更高效。先定位这块盘的 BDFlspci | grep -i non-volatile假设输出03:00.0 Non-Volatile memory controller接着lspci -vv -s 03:00.0 | grep -E LnkCap|LnkSta重点看这两行LnkCap: Speed 16GT/s, Width x4 LnkSta: Speed 8GT/s, Width x2LnkCap是链路最大能力LnkSta是当前协商结果。如果能力是 Gen4 x4协商只有 Gen3 x2那实际带宽直接砍到四分之一性能拉胯就是必然的。为什么协商失败可能是接口只支持一半通道数也可能是转接卡走线不对甚至金手指没插到位。lspci 告诉你“协商到了什么程度”剩下的物理层问题再去逐个排除。这里补充一个细节PCIe 链路协商是训练出来的主机和设备每次上电都会重新握手以两者中较低的速率和宽度为准。LnkSta括号里如果出现downgraded说明没有协商到最高能力即使能用也值得查一查。3.3 场景三想把物理设备直通给虚拟机先确认 BDF 和多功能分组做虚拟化设备直通时你要直通的往往不是一个简单的设备而是一个“多功能设备组合”。比如某些网卡做成了双口在 PCI 层面表现为同一个物理槽位上的两个 function也就是01:00.0和01:00.1。先lspci -nnk列出所有网络设备确认要直通的两个功能分别是什么再看-s 01:00能不能把两个 function 都列出来。如果设备在 IOMMU 分组里和别的设备绑在一起直通时会把一组全塞给虚拟机这时候 lspci 的输出就能帮你快速判断要不要用 ACS 补丁拆分。我习惯在直通前把目标设备的 BDF、厂商 ID、设备 ID、当前驱动记录到一张表里然后统一执行解绑、绑定 vfio 的一串命令。整个过程里 lspci 承担的角色就是“对照表”和“验收工具”直通前看一遍直通后再看一遍两次输出一对比驱动状态从原来的网卡驱动变成vfio-pci就知道绑定成功了。4. lspci 不是孤军奋战和 dmesg、sysfs、pci.ids 配合才完整4.1 lspci -k 显示的“模块”怎么核对dmesg 与 modinfo 联动lspci -k只说“当前有哪些模块可以驱动这个设备”但模块为什么没被加载、加载后为什么报错这些 lspci 管不了得靠 dmesg。常见联动写法lspci -nnk | grep -iA3 ethernet dmesg | grep -iE eth|pci|error | tail -n 50有个印象很深的例子某网卡装上后lspci -k里Kernel modules有驱动模块但Kernel driver in use是空的同时 dmesg 里出现固件缺失的提示。原因就是驱动模块注册成功了但加载固件失败直接初始化中止。光看 lspci 会以为没驱动一翻 dmesg 真相大白。所以 lspci 负责给你“体检报告”dmesg 才是“病历本”两者始终要搭配着看。再看驱动模块本身的依赖关系可以用modinfo 模块名能看到作者、描述、依赖、参数这些信息。有时候Kernel modules列出三个候选模块但系统因为参数冲突或别名匹配原因加载了不对的那个这时候 modinfo 和 modprobe 的排查路线就派上用场了。4.2 从 lspci 到 /sys/bus/pci/devices内核视角的设备目录lspci 的数据来源之一就是 sysfs内核枚举完 PCI 设备后会在/sys/bus/pci/devices/下为每个设备建一个目录目录名就是带 domain 前缀的完整 BDF比如/sys/bus/pci/devices/0000:01:00.0/进目录看一下ls /sys/bus/pci/devices/0000:01:00.0/里面有vendor、device、class、irq、enable、resource、config等文件。cat vendor输出的就是 16 进制厂商 ID和 lspci -n 的结果完全一致。driver是一个符号链接指向当前绑定驱动的 sysfs 目录如果设备没驱动这个链接会不存在。sysfs 的价值在于它是“可编程的”脚本里可以直接读文件判断设备状态比解析 lspci 文本更稳定。比如检查某个 PCIe 设备是否被正确绑定到 vfio-pci直接readlink /sys/bus/pci/devices/0000:03:00.0/driver就能判断。lspci 适合人眼快速查看sysfs 适合机器做自动化判断两者各有所长。4.3 pci.ids 数据库三十岁之后怎么办update-pciids 的重要性前面提到过lspci 输出的设备名称来自 pci.ids 数据库。用户装好系统后如果没有更新过这个文件遇到新出的显卡、新出的网卡lspci 只能打印Unknown device。有一个朋友更新内核后网卡名字变怪查了半天才发现是 pci.ids 老掉牙了。解决办法很简单update-pciids这个命令会从网络拉一份最新的 pci.ids 到本地需要 root 权限。数据库路径因发行版不同有的在/usr/share/misc/pci.ids有的在/usr/share/hwdata/pci.ids。如果离线环境也可以手动下载文件放到对应路径但注意校验好权限和完整性。更新完再跑一次lspci -nn之前显示Unknown device的设备基本都能认出型号了。这个操作成本极低建议新装完系统就顺手做一次避免后面排查时被“假未知”干扰。5. 常见坑位全记录这几件事我当年花了不少时间才弄明白5.1 为什么某些设备在 lspci 里完全消失lspci 显示的是“当前主机枚举到的所有 PCI 总线信息”注意这个“当前”它只反映系统启动后实际枚举到的设备。设备没出现不代表硬件坏了先检查三件事BIOS/UEFI 里是否禁用了对应控制器常见于板载网卡、SATA 控制器设备在 PCIe 链路训练阶段就失败了插槽接触不良、线缆问题设备挂在没被系统枚举的总线范围内多处理器或多 domain 系统尤其容易出现另外某些笔记本的独显在未启用时可能不枚举或者被 ACPI 机制隐藏直到系统通过特定回调把它唤醒。这种情况 lspci 里看不到显卡但 dmesg 可能有相关提示。排查时不要只盯着 lspci把 dmesg 里所有含 pci 的行过一遍经常能找到隐藏线索。5.2 LnkSta 显示的协商速度远低于标称问题出在哪协商速度低于标称原因可能是链路训练失败后降级、插槽宽度不够、或者是经过转接卡/线缆导致信号完整性变差。Gen3 的设备插到 Gen4 的槽里LnkSta会显示 Gen3 的速率这是正常现象反过来 Gen4 设备插到 Gen3 槽里也只会协商成 Gen3。只有能力匹配但协商不上才需要怀疑硬件链路问题。我遇到过一个特别容易忽略的情况有些消费主板的第二个 M.2 插槽和 SATA 口共用通道插了 SATA 盘后 M.2 的 PCIe 通道数会从 x4 降到 x2。lspci 里那块 NVMe 的LnkSta就会从Width x4变成Width x2性能直接砍半。这种问题不看LnkSta根本想不到。5.3 Kernel driver in use 为空的几种可能Kernel driver in use为空不代表驱动没装。至少有三类情况第一驱动确实没加载模块不在Kernel modules列表里需要装包或编译模块。第二驱动已经被 vfio-pci 接管但 lspci -k 在部分内核配置下不会把vfio-pci列为“in use”实际列出的可能是空。判断方法是用readlink看 sysfs 的 driver 链接或者lspci -nnk -s BDF再看一遍。第三驱动编译成了 built-in直接编进内核镜像。这种情况Kernel modules可能为空但设备能正常工作。不要一看到空就急着找驱动先确认设备本身是否可用。有种稳妥的验证思路dmesg | grep -i 设备名看内核有没有主动 probe 的记录lspci -v看设备能力是否正常初始化再不行就lspci -xxxx -s BDF把扩展配置空间 dump 出来对照规格书确认设备是否走到了可工作的状态。5.4 高频用法速查表粘贴进终端就能用命令作用lspci列出所有 PCI 设备lspci -nn列出所有设备并显示厂商/设备 IDlspci -nnk显示设备 ID 和内核驱动信息最常用lspci -s 01:00.0 -v查看指定 BDF 设备的详细配置lspci -vv -s 01:00.0查看指定设备的 PCIe 链路协商状态lspci -d 10de:按厂商筛选设备lspci -t查看设备树拓扑lspci -xxxx -s 01:00.0查看设备 4KB PCIe 扩展配置空间update-pciids更新本地 pci.ids 数据库这张表基本覆盖了日常 95% 的使用场景建议直接收藏。还有一个值得养成的习惯在高负载服务器上排查硬件问题前先lspci -nn存一份快照。机器出问题后对比快照和现状看哪些设备消失了、哪些设备多出来了、哪些设备的链路状态变了很多诡异问题其实都是硬件拓扑变化引起的。我在实际维护中吃过这个亏设备重启后多了一个设备没被发现结果性能问题排查了整整两天最后定位到是新增了一张采集卡抢占 PCIe 通道。从那以后每台新上线的机器我都会留下 lspci 原始输出当作基线存档成本几乎为零关键时刻价值极高。另外一个小技巧如果你和我一样经常在各种机器上敲lspci | grep可以在 shell 配置里加一个别名比如把lspci-nnk映射成lspci -nnk再配一个 color 输出和高亮 grep体验会舒服很多。Linux 下的排查工作往往就是这些小命令的组合拳lspci 这套打好了后面看 dmesg、看 sysfs、看驱动细节都顺理成章。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。