MmMapLockedPages在AccessMode设为UserMode时的作用及相关内存API疑问咨询
针对核心问题的逐一解答
MmMapLockedPages 传入AccessMode = UserMode的实际运行逻辑
这一操作不存在“让用户对仍处于系统空间的内存做受限查看”的设计——Windows的用户态/内核态地址空间是靠页表权限硬隔离的,用户态根本没有权限访问任何属于系统空间的虚拟地址,哪怕是内核驱动也没法绕过硬权限检查。
实际的运行逻辑是:
- 你需要提前通过
MmAllocatePagesForMdl这类API把连续物理页锁定在内存中,保证不会被系统换出到磁盘 - 调用
MmMapLockedPages时传入AccessMode = UserMode,内核会在你指定的目标进程的用户态虚拟地址空间中,找到一块对齐的空闲虚拟页范围,为这些已锁定的物理页建立独立的映射条目 - 映射的内存权限完全跟随锁页时设置的内存属性:如果锁的是可读写内存,用户态拿到的虚拟地址访问体验和通过
malloc分配的普通用户内存完全一致,没有额外限制;对用户侧内存的修改会直接写入对应的物理页,内核侧如果还保留着同一块物理页的系统空间映射,可以直接同步读取到修改内容,全程没有额外的内存拷贝。
需要注意的是,这个映射关系是绑定到目标进程的,驱动必须显式调用MmUnmapLockedPages完成解映射、释放锁定的物理页,不然会造成物理内存泄漏;哪怕目标进程提前退出,内核只会自动清理页表里的映射条目,不会帮你释放MDL持有的锁。
关于ZwAllocateVirtualMemory的相关疑问解答
针对你检索到的现象,对应的解释是:
- 为什么该函数被归类到「Previous Versions(旧版本)」栏目?
这并不意味着函数被废弃。ZwAllocateVirtualMemory是Windows原生NT执行体的内核态系统服务入口,对应用户态的NT层接口是NtAllocateVirtualMemory,大家熟悉的VirtualAlloc就是这个接口在Win32子系统层的封装。微软近年的公开文档策略是,优先为普通应用开发者维护Win32用户态API的文档,内核态使用的原生NT接口不属于面向普通开发者的稳定公开接口范围,因此被归档到旧版本分区——实际上从Windows XP到最新的Windows 11,这个函数始终在内核中正常运行,从未被移除。 - 和
VirtualAlloc相比的使用弊端
这两个不属于同一层级的接口,不存在直接同场景对比的可能:VirtualAlloc是kernel32.dll导出的用户态函数,内核驱动环境下根本无法直接调用它。
如果是在内核驱动开发场景下使用ZwAllocateVirtualMemory,确实有几个容易踩坑的注意点: - 调用时必须运行在被动级IRQL下,高IRQL环境调用会直接触发系统崩溃
- 接口本身不做上层的参数合法性校验,所有参数异常需要调用者自行兜底,参数配置错误会直接破坏目标进程的内存布局,甚至引入安全漏洞
- 如果是在目标用户进程的上下文之外调用这个接口分配用户空间内存,需要额外处理进程上下文切换逻辑,不像Win32层的
VirtualAlloc已经帮你完成了上下文对齐的处理。
补充说明
你提到“暂无公开文档记录的NT API可用于将内存放置到用户空间虚拟内存中”,实际上除了MmMapLockedPages,公开的内核API里的ZwMapViewOfSection同样可以实现将内核内存映射到用户地址空间的能力,只是日常开发中MmMapLockedPages的使用场景更直接。
内容的提问来源于stack exchange,提问作者FShrike
相关产品推荐
相关产品推荐

