windows驱动的DO_DIRECT_IO和DO_BUFFERED_IO

WINDOWS设备驱动 DO_DIRECT_IO和DO_BUFFERED_IO
2009-09-05 21:56
详细参照毛德操先生的《WINDOWS内核情景分析》9.12MDL章节。
两者都是WINDOWS设备的标志,而不是IRP的。一般的系统调用如NtReadFile和NtWriteFile等,都是由用户程序发起,且伴随大量 的数据交换。最简单的情景就是用户程序阻塞在系统调用上,待内核完成数据交换后再继续执行。这个期间内核运行于进程上下文,且中间不能存在内核抢占,也就 是说只能运行于一个进程的上下文。因为数据交换需要同时访问内核空间和用户空间,而用户空间是进程互异的。也就是说相同的虚拟地址在不同的进程里通常都表 示完全不相干的物理地址,所以一旦发生进程切换,而内核用原来的虚拟地址通常是无法获取正确的数据的。而涉及硬件操作的调用如,写磁盘等都只能采用异步、 中断的方式来处理,而中断函数以及其后的DPC函数都无法保证正确的操作用户空间。
解决方法有二。一,CPU进入内核空间后,先在内核空间申请合适大小的内存缓冲区然后把用户空间的数据复制到这里。因为所有的进程以及中断等都共享相同的内核空间页表,所以能保证CPU始终访问到正确的数据。这就是DO_BUFFERED_IO模式。
二,临时为用户空间的缓冲区增添一个系统空间映射,这样就使同一组物理页面有了两个虚拟地址空间,其一就在原来的用户空间虚拟地址,其二则在系统空间的虚 拟地址。这样即使发生进程切换,或者在中断函数、DPC函数里面访问都可以通过系统空间的虚拟地址来访问用户空间的缓冲区,直到操作完成返回用户空间时才 撤销系统空间。这就是DO_DIRECT_IO模式。
当然也可以两种方式都不用,但不可以同时使用这两种方式。如果两种方式都不用,那么必须要保证相应用户空间的缓冲区不会被中断程序或DPC函数访问。


附CSDN网站上的一篇:
http://blog.csdn.net/Like_Thinking/archive/2008/04/18/2304683.aspx
1、DO_DIRECT_IO还是DO_BUFFERED_IO?这两种方式有什么区别?分别对应什么情况使用?
答:
DO_DIRECT_IO 常用于传输大块的讲求速度的数据。DO_BUFFERED_IO常用于传输小块的,慢速的数据。DO_DIRECT_IO的效率较高(只需内存锁定即 可),代价是牺牲物理内存。DO_BUFFERED_IO的内存效率高,但速度差(它要分配内存,复制数据)。造成这种区别的主要原因还是因为处理器的 Ring 0到Ring4的穿越造成的(微软只用了两层)。你无法两全其美,只能取其一(当然有时候能两全其美,后面会提到)。
DO_DIRECT_IO主要用于使用DMA的底层驱动。Mass Storage也用。
DO_BUFFERED_IO主要用于HID(包括Mouse,Keyboard), 一些Video, 还有串口,并口什么的。
不过我看绝大多数设计者都挺自私的,上来就用DIRECT IO, :)

2、应用程序中writefile、readfile会进入ds封装好的write、read,但我如果在write、read中写了几个pipe的传输,怎么在应用程序中控制?
答:
我 没太看懂你是什么意思。我猜你是说如何在应用程序中控制Driver中的Read、Write函数中的执行细节-即有选择地执行指定的代码。如果是这样, 那你最好是加入IO CTRL或Vendor Request什么的外部控制。然后在Driver和固件中使用全局变量即可。

3、同步方式与异步方式与Isochronous Transfer有什么关系吗?
我理解的同步方式、异步方式是指对irp的处理,异步方式也可以建立Isochronous Transfer吧?

答:同步方式与异步方式是一种概念,到处都在使用,也更容易混淆和混乱。你可以在软件、通信、甚至电机领域都见得到他们。跟它们类似的还有“中断”-让论坛上的兄弟们头大的又一杀手!
你 说的“同步方式与异步方式”是指Request的操作模式。对应于软件中的编程。Windows更提倡采用异步方式,界面更友好,效率更高。同步方式更古 典,简单,适合初学者。简单地说,对于一个长时间的操作(放在一个函数里),异步操作立刻返回STATUS_PENDING,至于什么时候完成或超时,你 自己再去查询。同步操作会傻在那里直到操作完成或超时。如果做过串口编程或网络编程会很容易理解这两个概念。异步操作配合Windows的消息机制可以做 出很漂亮的接口和界面。
Isochronous Transfer则完全是USB的一种传输方式:主有用于多媒体流。你可以设想:如果Usb传输出错,对于资料传输(例如文件传输)而言事必要重发。而对 于音视频,则完全可以丢弃,因为同步连续才是最重要的。因为即便你重传,声音和图像也已经停顿或扰动了。所以同步传输关心的是在此时此刻把当前的数据发送 出去。完全不理会前一个包是否有问题。就像电视机一样,关注于实时性。
所以结论是:“我理解的同步方式、异步方式是指对irp的处理,异步方式也可以建立Isochronous Transfer”可以这样理解。

最 后,提到关于两全其美的事情:可以DO_DIRECT_IO和DO_BUFFERED_IO两种都不用,达到内存与效率兼顾。但是(说到“但是”总是令人 失望,真是没办法!)只能用于高层驱动程序(是指它运行于用户线程空间),诸如FSD等。这种IO方式的使用还有一堆罗里罗唆的要求,比如 ProbeForRead,ProbeForWrite什么的。初学者可以暂时不去玩它。

你可能感兴趣的:(编程,windows,IO,video,keyboard,磁盘)