ARTICLE · 1312981
从零开始学习PCIe软件开发(一)
从零开始学习PCIe软件开发(一)
PCIe是主流的高速设备互连标准,广泛应用于 GPU、NVMe SSD、高速网卡、FPGA 加速卡等设备。
对于驱动开发而言,学习 PCIe 不必一开始就深入复杂的物理层协议,而应首先理解:OS如何发现设备、CPU 如何访问设备寄存器、设备如何通过 DMA 传输数据,以及驱动如何处理中断和异常。
本文围绕Host 侧的普通 PCIe 设备驱动,梳理从基础知识到实际开发的学习路线。
一、系统架构
典型 PCIe 系统主要由 Root Complex、Endpoint和Switch 组成。
RC 连接主机 CPU、内存系统与 PCIe 总线,为设备枚举和访问提供硬件支持;EP 是 FPGA、NVMe SSD、网卡等终端设备;Switch 则用于扩展 PCIe 拓扑,连接多个 Endpoint。
二、协议基础
PCIe 协议分为事务层、数据链路层和物理层。
驱动开发应重点理解事务层的 TLP,包括 Memory Read/Write、Configuration Request、Completion 和 Message 等类型。
理解这些事务的完成语义和排序规则,有助于分析 MMIO 访问、DMA 控制和设备响应异常。
三、夯实 C 语言与内核基础
PCIe 驱动主要使用 C 语言开发,需要掌握指针、结构体、位操作、内存对齐、大小端转换以及资源生命周期管理。
Linux 内核方面,应重点学习 PCI Driver Model、内存管理、中断处理和并发同步机制。
四、三种关键地址
必须区分 CPU 虚拟地址、CPU 物理地址和 DMA 地址。
CPU 通过虚拟地址访问内存,而 PCIe 设备通过 DMA 地址访问主机缓冲区。
DMA 地址不一定等于 CPU 物理地址。 在启用 IOMMU 的系统中,设备使用的 DMA 地址可能需要经过地址转换。
五、通过实践建立开发能力
建议按照以下顺序逐步实践:
设备枚举 → BAR/MMIO 访问 → DMA 数据传输 → MSI/MSI-X 中断 → 设备管理与调试。
首先使用 lspci 分析 PCIe 拓扑和配置空间,再编写最小 PCIe 驱动,完成 BAR 映射和寄存器访问。
之后逐步实现 DMA 缓冲区管理、数据传输、中断通知、超时处理和数据校验,最终形成完整的驱动开发闭环。















































































