基础 驱动通信IO类型Buffered,Direct,Neither

   在和驱动通信过程中,我们一般都会碰到应该选择何种类型的缓冲类型进行通信。本文将简要的介绍一下这3中类型的IO缓冲。

   我想用的最多的就是Buffered这种IO进行的。现在来说说IO manager是如何对这3中类型的IO进行处理的。

   1.IO manager接收到由上层下发来的请求,这里假设这个请求既包含有输入缓冲,又有输出缓冲。这个看看DeviceIoControl中的参数中就可以既包含输入缓冲,又可以有输出缓冲。

   2.IO manager检查这个IRP是何种类型的。如果是Buffered的,那么IO Manager就会在NonPagePool中分配一个输入缓冲和输出缓冲之间最大的一个;如果是Direct形式的,那么就会首先将上传传下来的缓冲创建一个MDL给IRP。而如果是Neither类型的,那么直接就使用应用层传下来的缓冲。

   3.IO manager将IRP分派给指定的驱动进行处理。

   4.驱动中根据IO类型,得到合适的缓冲地址。如果是Buffered的,那么就是IRP的InBuffer和OutBuffer共同使用SystemBuffer;如果是Direct,那么Inbuffer 和OutBuffer使用MdlAddress;而如果是Neither那么就使用Type3Buffe(InBuffer)r和UserBuffer(OutBuffer).

   5.驱动返回,这里自然就是将IO manager分配的内存中的OutBuffer拷贝给应用层的Buffer中了。

 

    上面基本上说了个大概。对于IO manager具体是如何实现的,可以不用去理会。清楚知道什么类型的IO,应该从那个字段中得到Buffer地址就可以了。不过有些事需要值得注意的几点:

    1.用户层传下来的如果是Buffered类型的,那就直接使用即可。如果是direct类型的那么需要注意的是,在使用的时候需要将虚拟地址锁内存中进行使用。如果是Neither,因为这个是应用层的虚拟地址,而且这个虚拟地址是有进程上下文限制的,使用这个的时候务必使在指定的进程上下文中进行操作,如果不在制定的上下文可是使用KeStackAttachProcess 将驱动Attach到指定进程上面,然后在进行操作,不过要记得KeUnstackDetachProcess进行Detach。

    2.在进行缓冲移动中,如果是很大快内存,那么最好是使用MDL的方式。因为Buffered使用的是NonPagePool中分配内存,系统的NonPagePool是有限的,如何使用这种方式会降低系统性能。也可以使用Neither的方式,缺陷上面已经说了。

    

 

    最后说说Direct In 和Out 的区别吧。这个在使用的时候是通过锁进行了,在使用In类型之前,会有一个Read锁,而在Out之前,会在上面加一个写锁。

你可能感兴趣的:(基础 驱动通信IO类型Buffered,Direct,Neither)