关于MDL的一些事情
2013-06-27 12:10
501 查看
关于MDL的一些事情(未完)
(2011-05-25 18:26:30)转载▼
标签:
| 分类: 驱动/内核 |
一.MDL数据结构
MDL是用来建立一块虚拟地址空间与物理页面之间的映射,结构定义如下:
view plaincopy to clipboardprint?
typedef struct _MDL {
struct _MDL *Next;
CSHORT Size;
CSHORT MdlFlags;
struct _EPROCESS *Process;
PVOID MappedSystemVa; //StartVa+ByteOffset
PVOID StartVa; //页开始地址 4k对齐
ULONG ByteCount;
ULONG ByteOffset;
} MDL, *PMDL;
typedef struct _MDL {
struct _MDL *Next;
CSHORT Size;
CSHORT MdlFlags;
struct _EPROCESS *Process;
PVOID MappedSystemVa;
PVOID StartVa;
ULONG ByteCount;
ULONG ByteOffset;
} MDL, *PMDL;
各field的解释:
Next:MDL可以连接成一个单链表,这在IRP的结构里能找到。具体是做什么用的参考对IRP的描述
Size:一个MDL并不单单包含结构里这些东西,在内存中紧接着一个MDL结构,存着这个MDL对应的各个物理页面编号,由于一个物理页面一定是4KB对齐的,所以这个编号相当于一个物理页面起始地址的高20位。Size的值减去sizeof(MDL),等于存放编号的区域的大小。比如该MDL需要三个物理页面来映射虚拟地址空间,则Size-sizeof(MDL)==4*3==12;
MdlFlags:与这个MDL相关的一些标记
Process:如果虚拟地址是某一进程的用户地址空间,那么MDL代表的这块虚拟地址必须是从属于某一个进程,这个成员指向从属进程的结构
MappedSystemVa:该MDL结构对应的物理页面可能被映射到内核地址空间,这个成员代表这个内核地址空间下的虚拟地址。对MmBuildMdlForNonPagedPool的逆向表明,MappedSystemVa=StartVa+ByteOffset。这是因为这个函数的输入MDL,其StartVa是由ExAllocatePoolWithTag决定的,所以已经从内核空间到物理页面建立了映射,MappedSystemVa自然就可以这样算。 可以猜测,如果是调用MmProbeAndLockPages
返回,则MappedSystemVa不会与StartVa有这样的对应关系,因为此时对应的物理页面还没有被映射到内核空间。(此处未定,MmProbeAndLockPages 是否会到PDE与PTE中建立映射,未知。)
StartVa:虚拟地址空间的首地址,当这块虚拟地址描述的是一个用户进程地址空间的一块时,这个地址从属于某一个进程。
ByteCount:虚拟地址块的大小,字节数
ByteOffset:StartVa+ByteCount等于缓冲区的开始地址
二.对MmBuildMdlForNonPagedPool的黑盒测试
测试的程序主要执行如下步骤:
1.用 ExAllocatePoolWithTag在内核地址空间的NonpagedPool分配一块10000自己的区域
2.用上述得到的地址和大小调用IoAllocateMdl,返回一个MDL
3.打印该MDL个成员的值
4.调用MmBuildMdlForNonPagedPool
5.打印MDL各成员的值,比较与步骤3中的不同
代码如下:
view plaincopy to clipboardprint?
#include "ntddk.h"
#include "wdm.h"
#include "ntdef.h"
#define BUF_LENGTH 10000
static void OutputMDL(PMDL pMDL);
static void Unload( IN PDRIVER_OBJECT pDriverObject);
NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath )
{
PVOID pBuf = NULL;
PMDL pMDL;
//set up unload routing
pDriverObject->DriverUnload = Unload;
//allocate memory from non-paged pool
pBuf = ExAllocatePoolWithTag(NonPagedPool,BUF_LENGTH,(ULONG)DriverEntry);
if(!pBuf) {
DbgPrint("ExAllocatePoolWithTag failed.\n");
return STATUS_SUCCESS;
}
DbgPrint("MDL_TEST: pBuf=0xx\n",(ULONG)pBuf);
//allocate a MDL
pMDL = IoAllocateMdl(pBuf,BUF_LENGTH,FALSE,FALSE,NULL);
if(!pMDL) {
DbgPrint("IoAllocateMdl failed.\n");
ExFreePoolWithTag(pBuf,(ULONG)DriverEntry);
return STATUS_SUCCESS;
}
//print MDL right after IoAllocateMdl
OutputMDL(pMDL);
//
DbgPrint("****************************************\n");
//call MmBuildMdlForNonPagedPool
MmBuildMdlForNonPagedPool(pMDL);
//print MDL after MmBuildMdlForNonPagedPool is called
OutputMDL(pMDL);
//return
IoFreeMdl(pMDL);
ExFreePoolWithTag(pBuf,(ULONG)DriverEntry);
return STATUS_SUCCESS;
}
void Unload( IN PDRIVER_OBJECT pDriverObject)
{
DbgPrint("MDL_TEST: Unloading. 88\n");
}
void OutputMDL(PMDL pMDL)
{
int i;
ULONG * p = (ULONG*)(pMDL+1);
DbgPrint("MDL_TEST: Size=%d\n",pMDL->Size);
DbgPrint("MDL_TEST: MdlFlags=0xx\n",pMDL->MdlFlags);
DbgPrint("MDL_TEST: Process=0xx\n",(ULONG)pMDL->Process);
DbgPrint("MDL_TEST: MappedSystemVa=0xx\n",(ULONG)pMDL->MappedSystemVa);
DbgPrint("MDL_TEST: StartVa=0xx\n",(ULONG)pMDL->StartVa);
DbgPrint("MDL_TEST: ByteCount=%u\n",pMDL->ByteCount);
DbgPrint("MDL_TEST: ByteOffset=%u\n",pMDL->ByteOffset);
//print a few 4-bytes after the MDL structure
for(i=0;i<5;i++)
DbgPrint("MDL_TEST: p[%d]=0xx\n",i,p[i]);
}
#include "ntddk.h"
#include "wdm.h"
#include "ntdef.h"
#define BUF_LENGTH 10000
static void OutputMDL(PMDL pMDL);
static void Unload( IN PDRIVER_OBJECT pDriverObject);
NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath )
{
PVOID pBuf = NULL;
PMDL pMDL;
//set up unload routing
pDriverObject->DriverUnload = Unload;
//allocate memory from non-paged pool
pBuf = ExAllocatePoolWithTag(NonPagedPool,BUF_LENGTH,(ULONG)DriverEntry);
if(!pBuf) {
DbgPrint("ExAllocatePoolWithTag failed.\n");
return STATUS_SUCCESS;
}
DbgPrint("MDL_TEST: pBuf=0xx\n",(ULONG)pBuf);
//allocate a MDL
pMDL = IoAllocateMdl(pBuf,BUF_LENGTH,FALSE,FALSE,NULL);
if(!pMDL) {
DbgPrint("IoAllocateMdl failed.\n");
ExFreePoolWithTag(pBuf,(ULONG)DriverEntry);
return STATUS_SUCCESS;
}
//print MDL right after IoAllocateMdl
OutputMDL(pMDL);
//
DbgPrint("****************************************\n");
//call MmBuildMdlForNonPagedPool
MmBuildMdlForNonPagedPool(pMDL);
//print MDL after MmBuildMdlForNonPagedPool is called
OutputMDL(pMDL);
//return
IoFreeMdl(pMDL);
ExFreePoolWithTag(pBuf,(ULONG)DriverEntry);
return STATUS_SUCCESS;
}
void Unload( IN PDRIVER_OBJECT pDriverObject)
{
DbgPrint("MDL_TEST: Unloading. 88\n");
}
void OutputMDL(PMDL pMDL)
{
int i;
ULONG * p = (ULONG*)(pMDL+1);
DbgPrint("MDL_TEST: Size=%d\n",pMDL->Size);
DbgPrint("MDL_TEST: MdlFlags=0xx\n",pMDL->MdlFlags);
DbgPrint("MDL_TEST: Process=0xx\n",(ULONG)pMDL->Process);
DbgPrint("MDL_TEST: MappedSystemVa=0xx\n",(ULONG)pMDL->MappedSystemVa);
DbgPrint("MDL_TEST: StartVa=0xx\n",(ULONG)pMDL->StartVa);
DbgPrint("MDL_TEST: ByteCount=%u\n",pMDL->ByteCount);
DbgPrint("MDL_TEST: ByteOffset=%u\n",pMDL->ByteOffset);
//print a few 4-bytes after the MDL structure
for(i=0;i<5;i++)
DbgPrint("MDL_TEST: p[%d]=0xx\n",i,p[i]);
}
执行的结果如下:
view plaincopy to clipboardprint?
MDL_TEST: pBuf=0xadc92000
MDL_TEST: Size=40
MDL_TEST: MdlFlags=0x0008
MDL_TEST: Process=0x87e85c88
MDL_TEST: MappedSystemVa=0x95fb1cc4
MDL_TEST: StartVa=0xadc92000
MDL_TEST: ByteCount=10000
MDL_TEST: ByteOffset=0
MDL_TEST: p[0]=0x0002d72f
MDL_TEST: p[1]=0x0002e2b0
MDL_TEST: p[2]=0x0007e15a
MDL_TEST: p[3]=0x0007e15b
MDL_TEST: p[4]=0x0007e15c
****************************************
MDL_TEST: Size=40
MDL_TEST: MdlFlags=0x000c
MDL_TEST: Process=0x00000000
MDL_TEST: MappedSystemVa=0xadc92000
MDL_TEST: StartVa=0xadc92000
MDL_TEST: ByteCount=10000
MDL_TEST: ByteOffset=0
MDL_TEST: p[0]=0x0005bd23
MDL_TEST: p[1]=0x0005bea2
MDL_TEST: p[2]=0x0005bb21
MDL_TEST: p[3]=0x0007e15b
MDL_TEST: p[4]=0x0007e15c
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Squirrel_Program/archive/2009/11/15/4813674.aspx
相关文章推荐
- 关于MDL的一些事情
- 关于MDL的一些事情(未完)
- 关于MDL的一些事情
- 关于 Git 你需要知道的一些事情
- 关于xfs格式化的一些事情
- 关于WINDOWS 2003 SERVER作为域控制器的一些事情
- 关于一些暴力的事情:枚举(1)
- 关于项目管理中的一些事情,挑来说说
- 深夜的讨论——关于团队分工,以及我想到了一些关于国企的事情 [作者:马骏]
- 关于学习中的一些事情
- 关于IDataReader.GetSchemaTable的一些事情
- 关于C++ 编译 链接 的一些有趣的事情
- 关于bcache的一些事情
- 关于回车换行的一些事情
- 关于我的一些事情
- 关于训练时的一些事情
- 关于unity里面的UV的一些注意的事情
- 关于 Git 你需要知道的一些事情
- 关于 Git 你需要知道的一些事情
- 关于毕业的一些事情