Young87

当前位置:首页 >个人收藏

浅谈MDL(壹)(Windows内核学习笔记)

先说说MDL是个啥东西,看一下MSDN的定义:
Memory descriptor list. An opaque structure, defined by the Memory Manager, that uses an array of physical page frame numbers (PFNs) to describe the pages that back a virtual memory range.
内存描述符表。由内存管理器定义的一个不透明结构体,使用物理页帧号数组来描述支持虚拟内存的页。
听起来可高大上的一个解释,先来看看它的定义,分别在Windbg和**中的定义:

//Win10下的定义
//0x1c bytes (sizeof)
struct _MDL
{
    struct _MDL* Next;     		//0x0	MDL队列中的下一个成员
    SHORT Size;            		//0x4	整个MDL列表的长度,包括MDL结构体和物理页帧号所占的内存 物理页帧号起始地址紧跟在结构体后
    SHORT MdlFlags;        		//0x6	标志,设置一些内存属性
    struct _EPROCESS* Process;	//0x8	缓冲区所属进程
    VOID* MappedSystemVa;    	//0xc	映射之后的系统空间虚拟地址
    VOID* StartVa;       	 	//0x10	缓冲区所在第一个页面的虚拟地址
    ULONG ByteCount;       		//0x14	字节数,虚拟地址的大小
    ULONG ByteOffset;     	 	//0x18	StartVa + ByteOffset缓冲区开始的地址
}; 
//Win7的Windbg版本
0: kd> dt nt!_MDL
   +0x000 Next             : Ptr32 _MDL
   +0x004 Size             : Int2B
   +0x006 MdlFlags         : Int2B
   +0x008 Process          : Ptr32 _EPROCESS
   +0x00c MappedSystemVa   : Ptr32 Void
   +0x010 StartVa          : Ptr32 Void
   +0x014 ByteCount        : Uint4B
   +0x018 ByteOffset       : Uint4B

好像在Win7和Win下的定义,并没有什么变化。。。
为什么要使用MDL?
我们都知道在内核中运行的代码,可以访问用户层的内存空间,但是当线程调度发生,当前的页面映射表不再是之前的用户层进程的页面映射,但是CPU仍然访问原本的用户层虚拟地址,就会发生不可预知的错误,因为用户层的低2G虚拟空间空间是独立的。也就是说,我们访问到的地址可能并不是真正的目标地址。解决办法之一,就是使用MDL映射一份对应的物理内存到系统空间的虚拟地址中来,并且被MDL锁定之后,页面不会被换出。MDL只能在内核态使用,它可以指定对内核虚拟地址或者用户虚拟地址的映射。
接下来说一下MDL的使用:
对于很小的缓冲区来说,使用MDL不太划算,毕竟建立和撤销一个新的映射需要一定的开销,对于大一点的缓冲区可以使用。

除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog

上一篇: vue脚手架的安装

下一篇: 分离webpack.config.js文件后打包路径修改

精华推荐