使用DMA的直接IO

使用DMA的设备直接在用户缓冲区上进行IO操作:

上图说明了驱动怎样使用IRP中的MdlAddress来传输数据,此操作为读数据过程。上图中的驱动使用基于包的传输,bus-master模式或system模式都可以。

1、用户空间虚拟地址的某一范围,代表当前线程的缓冲区。缓冲区(虚拟地址空间)的内容实际上可能存储于一些物理上离散的页面中(如上图中的阴影部分)。IO管理器创建一个MDL来描述缓冲区。MDL是一个不透明的数据结构,由内存管理器定义。MDL用于将某一特殊的虚拟地址范围映射到一个或多个基于页的物理地址范围。

2、IO管理器为当前线程的读请求服务。线程传入一个用户空间地址范围,此地址范围代表了一个缓冲区。

3、IO管理器或FSDFile System Dispatch)检查用户适用的缓冲区是否可以访问,并调用MmProbeAndLockPagesMmProbeAndLockPages适用之前创建的MDL作为参数。MmProbeAndLockPages同时填满MDL中相应的物理内存。

如上图所示,表示虚拟地址的MDL可能有几个基于页的物理地址入口。缓冲区的虚拟空间范围可能起始和结束于某些字节偏移,例如,从MDL描述的页面中的第一页起始部分和最后一页起始部分。

4、IO管理器提供了一个MDL的指针,该指针存储于发起传输操作请求的IRP中。在驱动完成IRP的请求,IO管理器或文件系统调用MmUnlockPages函数之前,MDL中描述的物理页一直是锁定的,并且分配给了缓冲区。MDL中的虚拟地址能变成不可见的,甚至在IRP被送到设备驱动(或位于设备驱动上层的中间驱动)之前。

5、如驱动使用基于包的systembus-master DMA,它的AdapterControl例程调用MmGetMdlVirtualAddressMmGetMdlVirtualAddress使用IRP中的MdlAddress指针作为参数,以获取MDL的基于页的入口的虚拟地址基址。

6、AdapterControl例程调用MapTransfer,直接从设备中读取数据到物理内存。MapTransfer使用MmGetMdlVirtualAddress返回的基地址作为参数。

驱动必须时常检查缓冲区的长度。IO管理器并不为长度为0的缓冲区创建MDL

 

(本文议自于MSDN,不明之处请参考原文Using Direct I/O with DMA)

### DMA是否属于输入输出(I/O)操作 #### 定义与分类 DMA(Direct Memory Access,直接内存访问)是一种用于高效传输数据的技术,在计算机系统中起到重要作用。尽管DMA本身并不完全等同于传统的输入输出(I/O)操作,但从功能角度来看,它可以被视为广义上的I/O范畴的一部分[^1]。 #### 功能特性 DMA的主要特点是允许外部设备直接与主存进行数据交换而无需CPU介入过多细节处理。具体而言: - **数据路径独立性**:主存和DMA控制器间存在一条专门的数据通路,这使得在外设与主存之间传递信息时能够绕过CPU的操作干预。 - **并行作业支持**:因为不需要频繁打断当前运行中的程序来完成简单的数据搬运任务,所以实现了I/O活动与中央处理器工作的同步推进,从而提升了整体系统的性能表现。 #### 技术层面分析 虽然DMA减少了传统意义上由软件驱动的逐字节读写的必要性,并且其机制更接近底层硬件交互而非高层级的应用层面上定义的标准"I / O"行为模式,但是考虑到以下几点因素,则可以将其纳入到较为宽泛概念下的“I/O”类别当中考虑: - **资源分配角度**:如同其他形式的I/O事务一样,使用DMA也需要事先规划好相应的缓冲区设置以及后续可能涉及到的结果反馈流程管理等问题[^3]; - **目的导向视角**:无论是通过常规手段还是借助像DMA这样的特殊技术实现目标——即促进不同组件间的资料流通共享——本质上都是围绕着满足特定类型的Input(输入)/Output(输出)需求展开的工作内容之一部分[^4]。 综上所述,即使DMA在运作原理上有别于经典的基于轮询或中断触发式的标准I/O模型,但由于它同样服务于连接各类外围装置至核心计算单元这一共同使命之下,故此应当承认它是隶属于更大范围内的“输入输出”领域之内的一种重要组成部分。 ```python # 示例代码展示简单模拟DMA过程 class DMASimulator: def __init__(self, memory_buffer): self.memory_buffer = memory_buffer def transfer_data(self, device_data): # 假定这里执行的是从某个外设向内存缓冲区写入数据的过程 for byte in device_data: self.memory_buffer.append(byte) dma_simulator = DMASimulator([]) device_input_stream = [b'A', b'B', b'C'] dma_simulator.transfer_data(device_input_stream) print(dma_simulator.memory_buffer) # 输出应该是 ['A','B','C'] 表示成功进行了数据搬移动作 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值