4. UMDF DMA 支持:框架、通道、传输与缓冲区管理
UMDF 的 DMA 支持并非直接操作硬件 DMA 控制器,而是通过一套抽象框架,将 DMA 操作封装为 DMA 通道对象 和 DMA 传输对象,并配合 DMA 缓冲区管理 机制,实现与 PnP 管理器的协同工作。本章深入剖析这四个核心要素。
4.1 UMDF DMA 框架概述
UMDF DMA 框架位于驱动程序与内核 DMA 子系统之间,提供安全、简化的接口。其核心设计原则是:驱动运行在用户态,DMA 操作由内核态代理执行。
关键概念: UMDF 驱动不直接调用 WDM 的 DMA 函数(如
AllocateAdapterChannel),而是通过框架提供的 IWDFDmaTarget、IWDFDmaChannel 和 IWDFDmaTransaction 接口进行交互。框架负责与 PnP 管理器协商 DMA 资源,并管理映射寄存器。
4.2 DMA 通道对象 (IWDFDmaChannel)
DMA 通道对象代表一个逻辑 DMA 通道,它封装了与 PnP 管理器协商的 DMA 资源。每个通道对象对应一个 DMA 适配器对象,由框架在驱动创建设备时自动创建。
| 属性/方法 | 说明 | 典型值/行为 |
|---|---|---|
GetDmaAdapter | 获取关联的 DMA 适配器对象 | 返回 IWDFDmaTarget 接口 |
GetMaximumTransferLength | 获取单次传输最大字节数 | 由 PnP 管理器根据系统资源决定 |
GetMaximumFragmentLength | 获取单个 Scatter/Gather 片段最大长度 | 通常为 PAGE_SIZE 或更小 |
GetTransferAlignment | 获取传输对齐要求 | 通常为 4 或 8 字节对齐 |
MapTransfer | 将用户态缓冲区映射为 DMA 物理地址 | 返回 IWDFDmaTransaction |
调试要点: 在 WinDbg 中使用
!umdfdma 扩展命令可以查看当前设备的所有 DMA 通道对象及其状态。注意检查 GetMaximumTransferLength 的返回值,如果小于预期,可能是 PnP 资源分配受限。
4.3 DMA 传输对象 (IWDFDmaTransaction)
DMA 传输对象代表一次具体的 DMA 数据传输操作。它管理传输的 生命周期:初始化、执行、完成、取消。驱动通过调用 IWDFDmaChannel::MapTransfer 创建传输对象。
4.3.1 传输对象关键方法
- Initialize:绑定传输对象到 DMA 通道和缓冲区,设置传输方向(读/写)。
- Execute:启动 DMA 传输。框架会向内核提交传输请求,并返回一个
IQueueCallbackDmaCompletion回调。 - Cancel:取消正在进行的传输。框架会尝试中止 DMA 操作,但无法保证立即停止。
- GetTransferInfo:获取传输状态,包括已传输字节数、错误码等。
常见陷阱: 传输对象在
Execute 返回后,驱动不能立即释放缓冲区。必须等待 IRequestCompletionRoutine 回调,确认传输完成或失败后,才能安全释放或重用缓冲区。
4.4 DMA 缓冲区管理
UMDF 的 DMA 缓冲区管理涉及 用户态虚拟地址 与 物理地址 的映射。框架提供两种缓冲区分配方式:
| 分配方式 | API | 特点 | 适用场景 |
|---|---|---|---|
| 框架分配 | IWDFDmaTarget::CreateDmaBuffer | 自动映射到用户态,保证物理连续 | 小数据量、固定大小缓冲区 |
| 驱动分配 | IWDFDmaChannel::MapTransfer | 使用驱动预分配的缓冲区,需手动映射 | 大数据量、动态大小、零拷贝需求 |
4.4.1 缓冲区映射流程
- 分配缓冲区:驱动在用户态分配内存(如
VirtualAlloc或框架 API)。 - 锁定缓冲区:调用
IWDFDmaChannel::MapTransfer,框架将用户态虚拟地址锁定并映射为物理地址。 - 获取 Scatter/Gather 列表:框架返回
IWDFDmaTransaction,驱动通过GetTransferInfo获取物理地址片段列表。 - 启动传输:驱动将 Scatter/Gather 列表传递给硬件,启动 DMA。
- 解除映射:传输完成后,框架自动解除映射,驱动可安全访问缓冲区。
4.5 与 PnP 管理器的交互
PnP 管理器在以下关键点与 UMDF DMA 框架交互:
- 设备启动:PnP 管理器分配 DMA 资源(如 DMA 通道号、映射寄存器数量),框架据此创建
IWDFDmaChannel。 - 资源重新平衡:当系统资源变化时,PnP 管理器可能重新分配 DMA 资源。框架会暂停所有传输,销毁旧通道,创建新通道。
- 设备移除:PnP 管理器通知框架释放所有 DMA 资源,框架自动取消所有未完成的传输并销毁通道对象。
调试技巧: 在资源重新平衡场景中,使用
!umdfdma -v 观察通道对象的 State 字段。如果状态长时间停留在 DmaChannelStatePendingStop,说明驱动未及时完成传输,导致 PnP 操作阻塞。
4.5.1 典型交互序列
| 步骤 | PnP 管理器 | UMDF 框架 | 驱动 |
|---|---|---|---|
| 1 | 发送 IRP_MN_START_DEVICE | 解析 DMA 资源描述符 | 接收 IPnpCallbackHardware::OnPrepareHardware |
| 2 | — | 创建 IWDFDmaTarget 和 IWDFDmaChannel | 调用 IWDFDmaTarget::CreateDmaBuffer 预分配缓冲区 |
| 3 | — | 注册 DMA 完成回调 | 实现 IQueueCallbackDmaCompletion |
| 4 | 发送 IRP_MN_QUERY_STOP_DEVICE | 暂停所有 DMA 通道,等待传输完成 | 停止提交新传输,等待回调 |
| 5 | 发送 IRP_MN_STOP_DEVICE | 销毁 DMA 通道对象 | 释放缓冲区,清理资源 |
性能优化: 对于高频 DMA 传输,建议在
OnPrepareHardware 中预分配多个 DMA 缓冲区,并使用传输对象池(IWDFDmaTransactionPool)避免运行时频繁分配/释放。