IoAllocateMdl,MmProbeAndLockPages的用法
转载地址:https://blog.csdn.net/wdykanq/article/details/7752909
IoAllocateMdl,MmProbeAndLockPages的用法
第一,MDL的一个用法是提供驱动程序访问用户模式数据缓冲区的一种方式:直接I/O。也就是说通过MDL告诉驱动程序如何访问用户模式的数据缓冲区,这很好理解;
第二,第二个用法是这样的,一些驱动程序在执行直接 I/O 来满足设备 I/O 控制请求时也使用 MDL,常用的方式如下:
1,分配一个buf,可能是分页或者非分页的;
2,调用IoAllocateMdl,指向这个buf;
3,对于分页内存来说,调用MmProbeAndLockPages以及MmGetSystemAddressForMdlSafe来锁定内存页,以防止被page out出去;
对于非分页内存而言,调用MmBuildMdlForNonPagedPool映射到物理内存上。
对于第二个用法,对于分页内存可能还有意义,保证其不被page out,但对于非分页内存,我觉得除了DMA以外,别的都没有用处,既然已经是非分页内存了,直接使用就好了,为什么还要生成一个MDL去做映射?我一直都不是非常理解,有可能根本就是理解错误,请大家指教
IoAllocateMdl
IoAllocateMdl 函数分配足够映射一块缓存的MDL,给定缓存的起始地址和长度.
PMDL
IoAllocateMdl(
__in_opt PVOID VirtualAddress,
__in ULONG Length,
__in BOOLEAN SecondaryBuffer,
__in BOOLEAN ChargeQuota,
__inout_opt PIRP Irp
OPTIONAL
);
驱动可以使用IoAllocateMdl 函数实现大缓存分片的目的,通过一个独立的MDL来映射缓存的一小部分,或者映射驱动分配的内存.驱动会调用MmBuildMdlForNonPagedPool 来设置MDL的内存,使得MDL描述驱动分配的缓存处于不可置换的内存中。
Length参数指明了MDL指向的缓存的大小。在Windows Server 2003, Windows XP, 和Windows 2000, 能够分配的最大缓存字节数为PAGE_SIZE * (65535 -
sizeof(MDL)) / sizeof(ULONG_PTR)。在Windows Vista和Windows Server 2008, 最大缓存字节数是(2GB - PAGE_SIZE).在Windows 7和Windows Server 2008 R2中, 最大缓存字节数是(4GB - PAGE_SIZE).
如果SecondaryBuffer参数是FALSE, 这个函数会更新Irp->MdlAddress ,让它指向一个新的MDL,
也就是说让它支持大缓存分片吧。 如果SecondaryBuffer为TRUE, 这个函数把MDL添加到Irp->MdlAddress指向的链之后。
MDL(memory descriptor list)
http://hi.baidu.com/reversefish/blog
typedef struct _MDL {
struct _MDL *Next;
CSHORT Size;
CSHORT MdlFlags;
struct _EPROCESS *Process;
PVOID MappedSystemVa;
PVOID StartVa;
ULONG ByteCount;
ULONG ByteOffset;
} MDL, *PMDL;
MDL只是一个对物理内存的描述,但是因为系统跟Driver都是使用虚拟内存,所以MDL就是把虚拟内存『映射』到物理内存(from DDK)。这样讲是很模糊的,其实MDL的作用很简单:当Driver要存取某段内存位置时,确保MDL所描述的内存位置不会引起page fault。
取得MDL的虚拟内存位置。 DDK特别讲明,Lower-Level Driver不可以直接把这个Address拿来使用,因为这有可能是user-space的内存位置。因此,Driver必须呼叫MmGetSystemAddressForMdlSafe()来取得并锁定这个Address所对应到的system-space的内存位置。
如果Driver希望建立的MDL是映射到Driver自己配置的Non-Paged记忆体的话,Driver还得呼叫MmBuildMdlForNonPagedPool()。这是因为IoAllocateMdl()只有配置记忆体,但是并没有Build MDL
临时为用户空间缓冲区增添一个系统空间映射,这使同一组物理页面有了两个虚拟地址区间,其一就是原来的用户空间虚拟地址区间,其二则是系统空间的虚拟地址区间。于是,就可以通过系统空间的虚拟地址访问用户空间缓冲区了,直到完成操作而返回用户空间时才撤销系统空间的映射。这种方法称为“直接”方法。直接方法对于很小的缓冲区是不划算的,因为临时映射的建立和撤销需要一定的开销,对于大一点的缓冲区才合适。
1.用户态到内核态
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);
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));
IoAllocateMdl,MmProbeAndLockPages的用法的更多相关文章
- -------- Rootkit 核心技术——利用 nt!_MDL 突破 KiServiceTable 的只读访问限制 Part II --------
------------------------------------------------------------------------------------------- 本篇开始进入正题 ...
- Windows内存放血篇,突破物理内存的CopyOnWrite
本篇以x86(开启PAE) 以及x64 Win7系统 不借助微软API突破内存的写拷贝机制进行讲述 https://bbs.pediy.com/thread-222949.htm 0x01 B ...
- 一个mdl相关的问题
感觉挺有意义的,细节问题 http://www.kernelmode.info/forum/viewtopic.php?f=14&t=4318这个人代码到底犯了什么错误 I want to p ...
- EditText 基本用法
title: EditText 基本用法 tags: EditText,编辑框,输入框 --- EditText介绍: EditText 在开发中也是经常用到的控件,也是一个比较必要的组件,可以说它是 ...
- jquery插件的用法之cookie 插件
一.使用cookie 插件 插件官方网站下载地址:http://plugins.jquery.com/cookie/ cookie 插件的用法比较简单,直接粘贴下面代码示例: //生成一个cookie ...
- Java中的Socket的用法
Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...
- [转载]C#中MessageBox.Show用法以及VB.NET中MsgBox用法
一.C#中MessageBox.Show用法 MessageBox.Show (String) 显示具有指定文本的消息框. 由 .NET Compact Framework 支持. MessageBo ...
- python enumerate 用法
A new built-in function, enumerate() , will make certain loops a bit clearer. enumerate(thing) , whe ...
- [转载]Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
本文对Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法进行了详细的总结,需要的朋友可以参考下,希望对大家有所帮助. 详细解读Jquery各Ajax函数: ...
随机推荐
- POJ3709 K-Anonymous Sequence
题意 Language:Default K-Anonymous Sequence Time Limit: 4000MS Memory Limit: 65536K Total Submissions: ...
- RCNN,Fast RCNN,Faster RCNN 的前生今世:(4) Fast RCNN 算法详解
继2014年的RCNN之后,Ross Girshick在15年推出Fast RCNN,构思精巧,流程更为紧凑,大幅提升了目标检测的速度.在Github上提供了源码. 同样使用最大规模的网络,Fast ...
- 模拟赛20181101 雅礼 Wearry 施工 蔬菜 联盟
% Day2 Solution % Wearry % Stay determined! 施工 记 fif_{i}fi 表示考虑前 iii 个建筑, 并且第 iii 个建筑的高度不变的答案, 每 ...
- Tensorflow细节-P54-变量
1.首先复习前面所学知识: (1)g = tf.Graph() (2)别忘了初始化时的initializer (3)with tf.name_scope("generate_constant ...
- Kubernetes 学习19基于canel的网络策略
一.概述 1.我们说过,k8s的可用插件有很多,除了flannel之外,还有一个流行的叫做calico的组件,不过calico在很多项目中都会有这个名字被应用,所以他们把自己称为project cal ...
- Kubernetes 学习4 kubernetes应用快速入门
一.相关命令 1.kubectl 通过连接api server 进行各k8s对象资源的增删改查,如pod,service,controller(控制器),我们常用的pod控制器replicaset,d ...
- 01_搭建新浪云SAE
Step1:注册新浪云计算平台用新浪微博登陆新浪云计算平台,网址:http://sae.sina.com.cn/ 登陆成功之后会跳转到安全设置页面,安全设置页面要填写的东西比较多,需要注意:安全设置里 ...
- Logparser
http://www.microsoft.com/en-us/download/details.aspx?id=24659 Logparser 的用法 https://www.cnblogs.com/ ...
- codevs6003一次做对算我输
6003 一次做对算我输 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 大师 Master 题目描述 Description 更新数据了!!!!!!!更新数据了!!!!!! ...
- 【概率论】5-10:二维正态分布(The Bivariate Normal Distributions)
title: [概率论]5-10:二维正态分布(The Bivariate Normal Distributions) categories: - Mathematic - Probability k ...