lspci不显示实时带宽,仅通过LnkCap(硬件能力)和LnkSta(实际协商)寄存器反映速率与宽度;真值需交叉验证sysfs的current_link_speed/width、dmesg错误及物理插槽规格。

lspci 本身不显示实时带宽,它只读取 PCIe 配置空间里的静态寄存器(LnkCap 和 LnkSta),反映的是链路能力与协商结果,不是吞吐量。真要判断带宽是否受限,得交叉验证三处关键数据源。
怎么看 lspci -vv 里真正的速率和宽度
lspci -vv 输出中没有 “Bandwidth” 字段,别被误导。有效信息藏在两行里:
- LnkCap: 行中的 Speed 和 Width:设备**硬件支持的最大能力**,比如 Speed 16GT/s, Width x16
- LnkSta: 行中的 Speed 和 Width:设备**上电后实际协商的结果**,比如 Speed 8.0GT/s, Width x4常见误判点:
- 看到
LnkCap: Speed 16.0GT/s就以为是 PCIe 4.0 —— 实际可能是老版本pciutils(<3.10.0)把 PCIe 5.0 也标成 16.0GT/s,需升级工具或交叉验证 -
LnkSta显示Speed: Unknown或整行缺失 → 内核未启用 AER,或 BIOS 禁用了链路状态报告 -
Width: x0出现在输出里 → 物理连接失败或设备未初始化成功,不是“零带宽”,而是链路根本没训起来
为什么 /sys/bus/pci/devices/xxx/current_link_* 更可信
内核通过 sysfs 暴露的 current_link_speed 和 current_link_width 是运行时从硬件寄存器直接读取的值,比 lspci 更接近真实状态。
操作步骤:
- 先用
lspci | grep -i nvme找到设备地址,比如0000:09:00.0 - 检查路径是否存在:
ls /sys/bus/pci/devices/0000:09:00.0/ - 读取当前值:
cat /sys/bus/pci/devices/0000:09:00.0/current_link_speed(输出如8.0,单位 GT/s) - 读取最大能力:
cat /sys/bus/pci/devices/0000:09:00.0/max_link_speed
关键差异:
-
current_link_speed值是纯数字(如8.0),lspci的LnkSta还带单位(8.0GT/s),解析脚本更易处理 - 某些设备(尤其是 OCP 网卡或 BMC 直连设备)的 sysfs 值存在而
lspci -vv无LnkSta行,此时只能信 sysfs - 若
current_link_speed明显低于max_link_speed,基本可断定是主板布线、BIOS 设置或插槽共享导致的降速
批量提取所有设备实际 PCIe 速率的可靠命令
手动翻lspci -vv 不现实,但直接解析容易漏掉无 LnkSta 的设备。推荐分两步:
先用 lspci 提取有链路状态的设备:
lspci -vv | awk '/^([0-9a-f]{2}:[0-9a-f]{2}\.[0-9])/ { dev=$1 } /LnkSta:/ && /Speed: [0-9.]+GT\/s.*Width: x[0-9]+/ { gsub(/,/,"",$0); print dev, $2, $4 }'再补上 sysfs 数据(更全):
for d in /sys/bus/pci/devices/*; do [ -e "$d/current_link_speed" ] && echo "$(basename $d) $(cat $d/current_link_speed) $(cat $d/current_link_width)"; done | sort
注意:
- 第二条命令会列出所有已识别的 PCIe 设备,包括 USB 控制器、SATA 主控等,需按设备类过滤(如加
| grep -E "nvme|nvidia|10ec|144f") - 某些设备(如集成声卡)可能有
current_link_speed但值为2.5(PCIe 1.0),这属于正常设计,不是故障 - 若某设备在两条命令中均无输出,大概率是未被内核枚举(
dmesg | grep -i "pcie|aer"查初始化错误)
带宽换算时最容易忽略的编码开销
看到Speed 16.0GT/s, Width x4 就直接算 16 × 4 = 64 GB/s?错。
必须乘以编码效率系数:
- PCIe 3.0/4.0/5.0:用
128b/130b编码 → 效率 ≈128/130 = 0.9846 - PCIe 1.0/2.0:用
8b/10b编码 → 效率 =0.8
单向带宽(GB/s)= Speed (GT/s) × Width × 编码效率 ÷ 8
例如:
-
8.0GT/s × x4 × 0.9846 ÷ 8 = 3.938 GB/s(PCIe 3.0 x4,NVMe 常见) -
16.0GT/s × x8 × 0.9846 ÷ 8 = 15.754 GB/s(PCIe 4.0 x8)
这个除以 8 是把 bit 换成 byte,不是可选项。很多性能报告里写的 “x16 带宽 64 GB/s” 实际是双向总和,而 Linux 工具默认给的是单向理论值。


















