《Windows驱动开发技术详解》中说
在使用直接方式来读写设备的时候,操作系统会将用户模式下的缓冲区锁住,然后操作系统将这段缓冲区在内核模式地址再次映射一遍。这样,用户模式的缓冲区和内核模式的缓冲区都使用的是同一块物理内存,无论操作系统如果切换进程,内核模式的地址都保持不变。
操作系统先将用户模式的地址锁定后会使用MDL来记录这片内存。被记录的内存在物理内存上可能是离散的,但是在虚拟内存上一定是连续的。
其实说白了,MDL就是用来建立一块虚拟地址空间与物理页面之间的映射。
MDL结构被定义在wdm.h中。。。
typedef __struct_bcount(Size) struct _MDL {
struct _MDL *Next;
CSHORT Size;
CSHORT MdlFlags;
struct _EPROCESS *Process;
PVOID MappedSystemVa;
PVOID StartVa;
ULONG ByteCount;
ULONG ByteOffset;
} MDL, *PMDL;
结合MSDN来理解一下每一个成员:
struct _MDL *Next;
指向MDL链表中的下一个MDL结构。
CSHORT Size;
首先要知道,一个MDL里不只有结构里的这些数据,这些只是MDL的一个头部,在头部之后储存着这个MDL所对应的各种物理页面的编号,由于一个物理页面一定是4KB对齐的,所以这个编号相当于一个物理页面起始地址的高20位,这里Size的大小就是用于存放物理页面编号与MDL头部的总大小。
CSHORT MdlFlags;
这里指令了一些与当前MDL相关的标志。
struct _EPROCESS *Process;
如果虚拟地址是某一进程的用户地址空间,那么MDL代表的这块虚拟地址必须是从属于某一个进程,这个成员指向从属进程的结构。
PVOID MappedSystemVa;
该MDL结构对应的物理页面可能被映射到内核地址空间,这个成员代表这个内核地址空间下的虚拟地址。
PVOID StartVa;
虚拟地址空间的第一个物理页的地址。
ULONG ByteCount;
虚拟地址块的大小,字节数。
ULONG ByteOffset;
表示虚拟内存首地址相对于第一个物理页的偏移。
————————————————
版权声明:本文为CSDN博主「zacklin」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zacklin/article/details/7466563