linux可通过/sys/class/net//device/下文件直接读取网卡pci信息,无需ioctl或root权限;需先检查路径可读性,再用std::ifstream读取vendor/device等字段,id需查表或调用lspci映射厂商名。

直接读取 /sys/class/net/<iface>/device/</iface> 下的文件即可
Linux 的 sysfs 是内核暴露硬件信息的标准接口,网卡设备只要绑定了 PCI(或 USB、platform)总线,/sys/class/net/<iface>/device/</iface> 就会是一个指向真实设备目录的符号链接。不需要 ioctl、netlink 或 root 权限——只要路径可读(普通用户默认可读大部分字段)。
常见要读的字段:
-
/sys/class/net/eth0/device/vendor→ PCI vendor ID(十六进制,如0x15b3) -
/sys/class/net/eth0/device/device→ PCI device ID(如0x101e) -
/sys/class/net/eth0/device/subsystem_vendor和subsystem_device→ 厂商自定义子系统 ID -
/sys/class/net/eth0/device/uevent→ 包含MODALIAS=pci:v000015B3d0000101Esv000015B3sd00000001bc02sc00i00这类完整匹配串 -
/sys/class/net/eth0/device/physfn/(如果存在)→ 表明是 SR-IOV VF,可回溯到 PF
注意 /sys/class/net/<iface>/device</iface> 可能不存在或不可读
不是所有网卡都挂载在物理总线上。例如:
- 虚拟网卡(
veth、dummy、bridge)没有device目录,读取会失败(stat()返回 -1,errno == ENOENT) - 某些 platform 设备或 ACPI 定义的网卡可能只有
/sys/class/net/eth0/device/of_node/,但无 vendor/device 文件 - 容器中若未挂载
/sys全量(如只挂了/sys/class/net),device子目录会被截断
所以 C++ 代码里必须检查 access("/sys/class/net/eth0/device", R_OK) == 0 再继续,不能假设路径一定存在。
用 std::ifstream 读文本文件比 readlink() + open() 更稳妥
虽然 /sys/class/net/eth0/device 是符号链接,但直接读它指向的目标(比如 /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0)并不必要。更简单的是:打开 /sys/class/net/eth0/device/vendor 这类路径本身 —— 内核会自动解析符号链接并返回内容。
示例片段(不依赖第三方库):
#include <fstream>
#include <string>
std::string read_sysfs_str(const std::string& path) {
std::ifstream f(path);
if (!f.is_open()) return {};
std::string s;
std::getline(f, s); // sysfs 单行文本,末尾有 \n,需 trim
if (!s.empty() && s.back() == '\n') s.pop_back();
return s;
}
auto vendor = read_sysfs_str("/sys/class/net/eth0/device/vendor"); // 返回 "0x15b3"
</string></fstream>
不用 readlink() 解析路径,也不用 readdir() 遍历 —— 指定字段就读指定路径,快且确定。
PCI ID 查表需要自己维护或调用 lspci -mm
内核只提供十六进制 ID,不提供厂商/设备名。想把 0x15b3 映射成 “Mellanox Technologies”,有两条路:
- 静态内置映射表(轻量,适合嵌入式或固定环境,但需定期更新)
- 运行时调用
lspci -mm -n并解析输出(依赖外部命令,但数据准、覆盖全)
注意:lspci 的数据库文件(/usr/share/hwdata/pci.ids 或 /var/lib/pciutils/pci.ids)格式松散,手写 parser 易出错;不如直接跑命令更可靠。但得确保 PATH 中能找到 lspci,且目标系统已安装 pciutils。
真正容易被忽略的是:不同内核版本对某些虚拟设备(如 macvlan、ipvlan)是否创建 device 链接不一致,测试时务必覆盖你实际部署的 kernel 版本(5.4 / 5.15 / 6.1+ 行为可能不同)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











