MDL只是一个对物理内存的描述,但是因为系统跟Driver都是使用虚拟内存,所以MDL就是把虚拟内存『映射』到物理内存(from DDK)。这样讲是很模糊的,其实MDL的作用很简单:当Driver要存取某段内存位置时,确保MDL所描述的内存位置不会引起page fault。
1.用户态到内核态
typedef struct _MDL {
struct _MDL *Next;
CSHORT Size;
CSHORT MdlFlags;
struct _EPROCESS *Process;
PVOID MappedSystemVa;
PVOID StartVa;
ULONG ByteCount;
ULONG ByteOffset;
} MDL, *PMDL;
取得MDL的虚拟内存位置。 DDK特别讲明,Lower-Level Driver不可以直接把这个Address拿来使用,因为这有可能是user-space的内存位置。因此,Driver必须呼叫MmGetSystemAddressForMdlSafe()来取得并锁定这个Address所对应到的system-space的内存位置。
如果Driver希望建立的MDL是映射到Driver自己配置的Non-Paged记忆体的话,Driver还得呼叫MmBuildMdlForNonPagedPool()。这是因为IoAllocateMdl()只有配置记忆体,但是并没有Build MDL
临时为用户空间缓冲区增添一个系统空间映射,这使同一组物理页面有了两个虚拟地址区间,其一就是原来的用户空间虚拟地址区间,其二则是系统空间的虚拟地址区间。于是,就可以通过系统空间的虚拟地址访问用户空间缓冲区了,直到完成操作而返回用户空间时才撤销系统空间的映射。这种方法称为“直接”方法。直接方法对于很小的缓冲区是不划算的,因为临时映射的建立和撤销需要一定的开销,对于大一点的缓冲区才合适。
BaseAddr = OpenKernel32(); //映射kernel32的section到本进程的低2G空间
if (!BaseAddr)
{
KdPrint(("DriverEntry--OpenKernel32 failure!\n"));
return 0;
}
KdPrint(("BaseAddr: 0x%08x\n",BaseAddr));
//创建一个MDL
pMDL = IoAllocateMdl(BaseAddr,0x11c000,FALSE,FALSE,NULL);
if (!pMDL)
{
KdPrint(("pMDL == NULL\n"));
return 0;
}
_try
{
MmProbeAndLockPages(pMDL,UserMode,IoReadAccess);//一个指定的内存范围驻留,锁住内存页防止被交换出去
}
_except(EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("MmProbeAndLockPages exception\n"));
}
_try
{
pMapedAddr = MmMapLockedPagesSpecifyCache(pMDL,KernelMode,MmCached,NULL,FALSE,NormalPagePriority);//MDL中存储的physical address page映射到虚拟地址中
if (!pMapedAddr)
{
KdPrint(("pMapedAdd == NULL\n"));
return 0;
}
}
_except(EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("MmMapLockedPagesSpecifyCache exception\n"));
}
2.内核态到用户态
pShareMM_SYS=ExAllocatePool(NonPagedPool,1024);//size必须是page的整数倍
RtlZeroMemory(pShareMM_SYS,1024);
pShareMM_MDL=IoAllocateMdl(pShareMM_SYS,1024,FALSE,FALSE,NULL);
MmBuildMdlForNonPagedPool(pShareMM_MDL);
pShareMM_User=MmMapLockedPagesSpecifyCache(pShareMM_MDL,UserMode,MmCached,NULL,FALSE,NormalPagePriority);
KdPrint(("pShareMM_SYS的地址为: 0x%p\n",(PUCHAR)pShareMM_SYS));
KdPrint(("pShareMM_User的地址为: 0x%p\n",(PUCHAR)pShareMM_User));
参考资料
《程序员求职成功路》