【微知】如何写一个用户态扫描PCIe设备读取PCIe配置空间的程序?

背景

PCIe设备交互需要基于TLP报文,读取PCIe设备配置空间这些操作在linux内核比较方便,在用户态也有lspci、setpci等工具。如何自己手写一个用户态的PCIe设备,来扫描PCIe设备实现类似lspci的效果,本文是一个简单的实验借助 pciutils 库来扫描并显示系统里 PCI 设备的相关信息。

实现机制

libpci提供的接口来操作,包括分配pci句柄,初始化,扫描、读取信息,详细代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <pci/pci.h>

int main() {
    struct pci_access *pci;
    struct pci_dev *dev;

    pci = pci_alloc();
    if (!pci) {
        fprintf(stderr, "无法分配 PCI 访问对象\n");
        return 1;
    }

    pci_init(pci);
    pci_scan_bus(pci);

    for (dev = pci->devices; dev; dev = dev->next) {
        pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_CLASS);

        printf("设备: %02x:%02x.%x\n", dev->bus, dev->dev, dev->func);
        printf("  Vendor: 0x%04x (%s)\n", dev->vendor_id, 
               pci_lookup_name(pci, PCI_LOOKUP_VENDOR, dev->vendor_id, 0));
        printf("  Device: 0x%04x (%s)\n", dev->device_id, 
               pci_lookup_name(pci, PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id));
        printf("  Class:  0x%06x (%s)\n", dev->device_class, 
               pci_lookup_name(pci, PCI_LOOKUP_CLASS, dev->device_class, 0));
        
        for (int i = 0; i < 6; i++) {
            if (dev->base_addr[i]) {
                printf("  BAR%d: 0x%016llx (size=0x%x, type=%s)\n",
                       i, 
                       (unsigned long long)dev->base_addr[i],
                       dev->size[i],
                       (dev->flags[i] & PCI_BASE_ADDRESS_SPACE) ? "Memory" : "I/O");
            }
        }
        printf("------------------------\n");
    }

    pci_cleanup(pci);
    // 根据实际版本选择以下一种释放方式
    // pci_free(pci);           // 新版本
    // pci_free_dev(pci);       // 旧版本(如果有该函数)
    free(pci);                 // 直接使用 free()

    return 0;
}

主要接口说明:

pci_alloc():创建一个 PCI 访问对象,为后续操作分配必要的资源。
pci_init(pci):对 PCI 访问环境进行初始化,读取配置文件并加载相关驱动。
pci_scan_bus(pci):对系统中的 PCI 总线进行扫描,识别所有连接的 PCI 设备。
pci_fill_info():读取设备的关键信息,如设备 ID、基址寄存器(BARs)以及设备类别等。
pci_lookup_name()将 ID 转换为对应的文本描述。
pci_cleanup(pci):清理 PCI 访问环境。
free(pci):释放 PCI 访问对象所占用的内存。

编译:

yum install pciutils-devel #前置准备
gcc -o pci_info pci_info.c -lpci

实操

安装依赖库:
在这里插入图片描述

编译:
在这里插入图片描述
执行:可以看到扫描到不同的设备,并且BAR空间也扫描出来了。
在这里插入图片描述

综述

用户态实现对PCIe的扫描和读写,以及结合未来使用地址映射,可以做很多有意思的事情,本文仅仅是一个通道的建立。后面结合类似/dev/mem以及资源空间,然后映射到用户态空间可以做不少有意思的事。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值