不能对 /sys/bus/pci/devices/xxx/config 调用 mmap(),因其是 sysfs 动态生成的伪文件,无 page backing 且 file_operations 未实现 mmap 方法,调用会返回 -enodev 或 einval;必须使用 open() + lseek() + read() 方式读取。

Linux 下没有“PCI 配置空间映射文件”这种标准抽象——/sys/bus/pci/devices/ 下的 config 文件才是直接访问 PCI 配置空间的接口,但它不是 mmap-able 的普通文件,不能用 mmap() 读取;而 /proc/bus/pci/ 在现代内核中默认禁用且已废弃。想在 C++ 中安全、便携地读 PCI 配置空间,必须走 sysfs + lseek()/read() 路径,或调用内核提供的 pciconfig_iobase 接口(不推荐)。
为什么不能对 /sys/bus/pci/devices/0000:01:00.0/config 调用 mmap()
该文件是内核通过 sysfs 动态生成的伪文件,底层无真实 page backing,其 file_operations 未实现 mmap 方法。尝试 mmap() 会直接返回 -ENODEV 或触发 Invalid argument 错误(errno = EINVAL)。glibc 的 std::ifstream 或 fopen() 后调用 mmap() 同样失败。
- 检查方式:
strace cat /sys/bus/pci/devices/0000:01:00.0/config 2>&1 | grep mmap—— 不会出现成功 mmap 调用 - 替代方案:只能用
open()+lseek()+read(),每次最多读 4096 字节(PCI 配置空间共 256 字节,但内核强制按页对齐) - 注意:
read()从偏移 0 开始可读全部 256 字节;读越界(如 offset=256)会返回 0,不报错
如何用 C++ 安全读取指定设备的 PCI 配置空间
核心是拼出正确的 sysfs config 路径,并以只读方式打开,然后跳转到目标寄存器 offset 读取 4 字节(uint32_t)。需确保进程有权限(通常需 root 或 sysfs 权限组)。
- 路径格式为
/sys/bus/pci/devices/<code>DOMAIN:BUS:SLOT.FUNC/config,例如/sys/bus/pci/devices/0000:01:00.0/config - 用
std::fstream不可靠(内部可能缓冲/seek 异常),建议用 C 风格int fd = open(path.c_str(), O_RDONLY) - 读 Vendor ID(offset 0x00):
lseek(fd, 0x00, SEEK_SET)后read(fd, &val, sizeof(val)) == 4 - 读 BAR0(offset 0x10):
lseek(fd, 0x10, SEEK_SET),同样 read 4 字节;注意 BAR 是 little-endian,x86_64 上无需字节序转换 - 错误处理必须检查
lseek()返回值(失败时为 -1)和read()实际字节数(应严格等于 4)
读取时容易忽略的权限与兼容性问题
即使路径存在,open() 仍可能失败:一是权限不足(/sys/bus/pci/devices/*/config 默认仅 root 可读),二是内核禁用了该接口(CONFIG_SYSFS 或 CONFIG_PCI_SYSFS 未启用)。
- 权限修复:将用户加入
sys组,或临时chmod 644 /sys/bus/pci/devices/*/config(不推荐生产环境) - 验证接口可用:
ls -l /sys/bus/pci/devices/*/config应显示大小为 0 但可读;若不存在,说明设备未被内核识别或 sysfs PCI 支持被裁剪 - 容器环境需挂载
/sys(--privileged或显式--mount type=bind,source=/sys,target=/sys,readonly) - ARM64 平台某些固件(如 UEFI)可能不暴露完整配置空间,
read()到非标准 offset 可能返回全 0,需结合lspci -vvv -s 0000:01:00.0校验
真正麻烦的从来不是怎么读那 256 字节,而是确认你面对的是一个被内核完全枚举、sysfs 正确导出、且当前用户有权触达的 PCI 设备——路径拼错、权限漏掉、容器没挂载 /sys,三者任一都会让 open() 直接失败,而错误信息往往只报 “No such file or directory”,跟实际原因差很远。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











