驱动读写方式(缓冲区读写与直接读写)

本文转载自: http://www.programlife.net/device-flags.html

 

应用程序和驱动程序交互数据需要指定数据的交互方式,通过设置DEVICE_OBJECT的Flags成员来标志。有DO_BUFFERED_IO、DO_DIRECT_IO或者0。

DO_BUFFERED_IO:一般用于比较简单且不追求效率情况下的解决方案,把应用层(Ring3层)中内存空间中的缓冲数据拷贝到内核空间。IRP的AssociatedIrp.SystemBuffer成员指向内核中的缓冲区。

DO_DIRECT_IO:把应用层的地址空间映射到内核空间,这需要在页表中增加一个映射。当然这不需要程序员手工去修改页表,通过构造MDL就能实现这个功能。MDL可以翻译为“内存描述符链”,按业界传统习惯一律称之为MDL。IRP中的MDLAddress域是一个MDL的指针,从这个MDL中可以读出一个内核空间的虚拟地址。
可以通过调用MmGetSystemAddressForMdlSafe来获得内核空间所映射的虚拟地址。
通过MmGetMdlByteCount、MmGetMdlVirtualAddress、MmGetMdlByteOffset可以得到缓冲区的长度、虚拟内存地址、偏移量。

既不使用DO_BUFFERED_IO也不使用DO_DIRECT_IO(0):直接使用应用程序提供的缓冲区地址,缓冲区地址可以在派遣函数中通过IRP的UserBuffer字段获得。这种方式通常很少用到,用起来时需要格外小心,因为ReadFile可以传入一个NULL指针或者非法地址给驱动程序,在驱动程序中可以结合ProbeForWrite和try块来操作。
(P.S. 绝对不能在中断服务程序和DPC函数中使用用户空间虚拟地址。特别地,由于Windows设备驱动的异步性,许多操作其实是作为DPC函数得到执行的;所以一般而言实际的设备驱动不是采用缓冲方法就是采用直接方法。

你可能感兴趣的:(驱动读写方式(缓冲区读写与直接读写))