内核驱动中,调用API函数:
①
ExAllocatePoolWithTag
,分配内存。对应的释放内存函数:
ExFreePoolWithTag
。
②
IoAllocateMdl
,给定缓冲区的起始地址和长度,
IoAllocateMdl
例程分配内存描述符列表 (MDL) 足以映射缓冲区。对应的释放MDL函数:
IoFreeMdl。
③
MmBuildMdlForNonPagedPool
,
MmBuildMdlForNonPagedPool
例程接收指定非分页虚拟内存缓冲区的 MDL,并更新它以描述基础物理页。
④
MmMapLockedPagesSpecifyCache,MmMapLockedPagesSpecifyCache
例程将 MDL 描述的物理页面映射到虚拟地址,并使调用方能够指定用于创建映射的缓存属性。对应的解映射函数:
MmUnmapLockedPages。
PVOID MmMapLockedPagesSpecifyCache(
[in] PMDL MemoryDescriptorList,
[in] __drv_strictType(KPROCESSOR_MODE / enum _MODE,__drv_typeConst)KPROCESSOR_MODE AccessMode,
[in] __drv_strictTypeMatch(__drv_typeCond)MEMORY_CACHING_TYPE CacheType,
[in, optional] PVOID RequestedAddress,
[in] ULONG BugCheckOnFailure,
[in] ULONG Priority
);
如果
MmMapLockedPagesSpecifyCache
成功执行
,MmMapLockedPagesSpecifyCache
返回映射页面的起始地址。参数2选择
UserMode
,映射为用户模式虚拟地址。
应用程序通过
DeviceIoControl
获得映射页面起始地址,由此完成映射。
MmMapLockedPagesSpecifyCache
应在应用程序打开设备后框架调用的EVT_WDF_DEVICE_FILE_CREATE 回调函数中调用。
注意,映射完内存,在应用程序还没有退出时热插拔设备的情况下,内存的回收应在应用程序关闭对应的回调函数file close中进行。
Windows
驱动
跑在核心态(Kernel mode),
驱动
的调用者跑在
用户
态。如何使
用户
态进程与核心态
驱动
共享
内存
呢
我们知道32位
Windows
中,默认状态下虚拟空间有4G,前2G是每个进程私有的,也就是说在进程切换的时候会变化,后2G是操作系统的,所以是固定的。既然
用户
态进程和核心态
驱动
在同一个进程空间里,是不是只要直接传个
内存
地址过来,就可以访问了?理论上可以但实际上不行,因为用
(a)通过kernel命令行参数预留一些
内存
这种方法,适合于需要大块的物理连续的
内存
。
假设物理
内存
总量为256M。命令行参数中,指定 mem=224M。即只让
内核
使用前224M
内存
,忽略其余的
内存
。
这样,我们就有了32M的
内存
可用,
内存
起始物理地址为224*1024*1024。
在
内核
态,通过ioremap,就可以将此物理地址处
IoAllocateMdl IoAllocateMdl 函数分配足够
映射
一块缓存的MDL,给定缓存的起始地址和长度. PMDL IoAllocateMdl( __in_opt PVOID VirtualAddress, __in ULONG Length, __in BOOLEAN SecondaryBuffer, __in BOOLEAN ChargeQuota, __inout_opt PIRP Irp OPTIONAL
在上一篇博文中我们通过使用附加进程的方式得到了该进程的PEB结构信息,本篇文章同样需要使用进程附加功能,但这次我们将实现一个更加有趣的功能,在某些情况下应用层与
内核
层需要共享一片
内存
区域通过这片区域可打通
内核
与应用层的隔离,此类功能的实现依附于MDL
内存
映射
机制实现。
I/O多数是异步的(如DPC),在执行I/O的过程中
用户
模式
线程在不断切换,所以处理I/O时访问的虚拟地址已不是原先发出I/O请求的线程的地址,那样将发生错误。创建MDL将原先位于
用户
空间的缓冲区内容
映射
到系统空间,由于
用户
模式
内存
是切换的而系统
模式
内存
对所有进程都是不变的,故不会发生以上问题。
MDL只能在
内核
态使用,但它指定的虚拟
内存
即可以是
内核
态地址也可以是
用户
态地址。如果是
用户
态的地址你必须要自行弄清地址所在的进程上下文,因为不同的进程拥有不同的地址空间,即使地址的值一模一样它们包含的数据也一定完全不同。如果是
内核
态的地址那么事情会变的稍微简单点,因为在
内核
态地址空间是共享的,同一
首先查阅CSDN,在其中有这样的定义:
内存
描述符列表 (MDL) 是一个系统定义的结构,通过一系列物理地址描述缓冲区。执行直接 I/O 的
驱动
程序从 I/O 管理器接收一个 MDL 的指针,并通过 MDL 读写数据。一些
驱动
程序在执行直接 I/O 来满足设备 I/O 控制请求时也使用 MDL。
MDL分为两部分:固定长部分和变长部分,固定长部分结构如下:
Next:MDL可以连接成...