浅谈MDL(壹)(Windows内核学习笔记)
日期: 2020-04-09 分类: 个人收藏 382次阅读
先说说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下的定义,并没有什么变化。。。 除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
为什么要使用MDL?
我们都知道在内核中运行的代码,可以访问用户层的内存空间,但是当线程调度发生,当前的页面映射表不再是之前的用户层进程的页面映射,但是CPU仍然访问原本的用户层虚拟地址,就会发生不可预知的错误,因为用户层的低2G虚拟空间空间是独立的。也就是说,我们访问到的地址可能并不是真正的目标地址。解决办法之一,就是使用MDL映射一份对应的物理内存到系统空间的虚拟地址中来,并且被MDL锁定之后,页面不会被换出。MDL只能在内核态使用,它可以指定对内核虚拟地址或者用户虚拟地址的映射。
接下来说一下MDL的使用:
对于很小的缓冲区来说,使用MDL不太划算,毕竟建立和撤销一个新的映射需要一定的开销,对于大一点的缓冲区可以使用。
上一篇: vue脚手架的安装
精华推荐