mm学习笔记_05:虚拟内存核心与系统调用
mm学习笔记_05虚拟内存核心与系统调用基于 ReactOS ARM3 MM 源码ntoskrnl/mm/ARM3/virtual.c1. virtual.c 概述文件位置d:\reactos\ntoskrnl\mm\ARM3\virtual.c职责虚拟内存管理的核心实现以下关键系统调用NtAllocateVirtualMemory— 分配虚拟内存NtFreeVirtualMemory— 释放虚拟内存NtProtectVirtualMemory— 修改内存保护属性MmGetPhysicalAddress— 虚拟地址转物理地址MmCopyVirtualMemory— 跨进程内存拷贝2. NtAllocateVirtualMemory——完整路径文件virtual.c:44572.1 函数签名NTSTATUS NTAPINtAllocateVirtualMemory(IN HANDLE ProcessHandle,IN OUT PVOID*BaseAddress,IN ULONG_PTR ZeroBits,IN OUT PSIZE_T RegionSize,IN ULONG AllocationType,IN ULONG Protect);2.2 步骤一参数验证// 1. ZeroBits 检查不能超过最大值if(ZeroBitsMI_MAX_ZERO_BITS)returnSTATUS_INVALID_PARAMETER_3;// 2. AllocationType 合法性检查必须包含 MEM_COMMIT / MEM_RESERVE / MEM_RESETif(AllocationType~(MEM_COMMIT|MEM_RESERVE|MEM_RESET|...))returnSTATUS_INVALID_PARAMETER_5;if(!(AllocationType(MEM_COMMIT|MEM_RESERVE|MEM_RESET)))returnSTATUS_INVALID_PARAMETER_5;// 3. MEM_RESET 独占检查if((AllocationTypeMEM_RESET)(AllocationType!MEM_RESET))returnSTATUS_INVALID_PARAMETER_5;// 4. MEM_LARGE_PAGES 必须带 MEM_COMMITif((AllocationTypeMEM_LARGE_PAGES)!(AllocationTypeMEM_COMMIT))returnSTATUS_INVALID_PARAMETER_5;// 5. MEM_WRITE_WATCH 必须带 MEM_RESERVEif((AllocationTypeMEM_WRITE_WATCH)!(AllocationTypeMEM_RESERVE))returnSTATUS_INVALID_PARAMETER_5;// 6. MEM_PHYSICAL 必须带 MEM_RESERVE 且 Protect PAGE_READWRITEif((AllocationTypeMEM_PHYSICAL)...)...// 7. 保护属性验证ProtectionMaskMiMakeProtectionMask(Protect);if(ProtectionMaskMM_INVALID_PROTECTION)returnSTATUS_INVALID_PAGE_PROTECTION;// 8. 用户态参数捕获SEH 保护_SEH2_TRY{if(PreviousMode!KernelMode){ProbeForWritePointer(UBaseAddress);ProbeForWriteSize_t(URegionSize);}PBaseAddress*UBaseAddress;PRegionSize*URegionSize;}_SEH2_EXCEPT(...);// 9. 地址范围检查if(PBaseAddressMM_HIGHEST_VAD_ADDRESS)returnSTATUS_INVALID_PARAMETER_2;if(!PRegionSize)returnSTATUS_INVALID_PARAMETER_4;2.3 步骤二进程获取与附加// 如果是当前进程直接使用if(ProcessHandleNtCurrentProcess())ProcessCurrentProcess;else{// 否则以 PROCESS_VM_OPERATION 权限引用目标进程StatusObReferenceObjectByHandle(ProcessHandle,PROCESS_VM_OPERATION,PsProcessType,...);// 如果目标进程不是当前进程附加到目标进程地址空间if(CurrentProcess!Process){KeStackAttachProcess(Process-Pcb,ApcState);AttachedTRUE;}}2.4 步骤三MEM_RESERVE 主路径当未指定基址或指定 MEM_RESERVE 时1. 配额计费 PsChargeProcessNonPagedPoolQuota(sizeof(MMVAD_LONG)) 2. 分配 VADExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), SdaV) 3. 初始化 VAD - Vad-u.VadFlags.PrivateMemory 1 - Vad-u.VadFlags.Protection ProtectionMask - if (AllocationType MEM_COMMIT) Vad-u.VadFlags.MemCommit 1 4. 插入 VAD自动查找空闲地址 Status MiInsertVadEx(Vad, StartingAddress, PRegionSize, HighestAddress, MM_VIRTMEM_GRANULARITY, AllocationType) 5. 写回用户参数SEH 保护 *URegionSize PRegionSize; *UBaseAddress (PVOID)StartingAddress;2.5 步骤四MEM_COMMIT 主路径当指定已有地址即对已预留区进行提交1. 锁定地址空间MmLockAddressSpace(AddressSpace) 2. 检查进程是否将终止 3. 查找冲突/匹配 VAD Result MiCheckForConflictingNode(StartVpn, EndVpn, Process-VadRoot, ...) 4. 验证 VAD 类型不能是 VadAwe/VadDevicePhysicalMemory/VadLargePages 5. 验证地址范围在 VAD 内 6. 如果是非私有内存Section 映射 - 获取原型 PTE - 锁定 MmSectionCommitMutex - 遍历 PTE 写入模板 PTE - 更新 NumberOfCommittedPages 7. 如果是私有内存 - 更新 CommitCharge 和 Process-CommitCharge - MiLockProcessWorkingSetUnsafe - 遍历每个 PTE - MiMakePdeExistAndMakeValid确保页表存在 - 写入 DemandZero 格式的 PTE保护属性 软件 PTE 标记 - MiUnlockProcessWorkingSetUnsafe完整流程图NtAllocateVirtualMemory │ ├─ 参数验证 │ ├─ ZeroBits 范围检查 │ ├─ AllocationType 组合检查 │ ├─ Protect 合法性检查 │ ├─ 用户态参数 Probe │ └─ 地址范围检查 │ ├─ 进程获取与附加KeStackAttachProcess │ ├─ [MEM_RESERVE 分支] │ ├─ 配额计费 │ ├─ 分配 VADExAllocatePoolWithTag │ ├─ VAD 初始化 │ └─ MiInsertVadEx自动搜索 Avl 插入 │ ├─ [MEM_COMMIT 分支] │ ├─ MmLockAddressSpace │ ├─ 查找已有 VADMiCheckForConflictingNode │ ├─ 验证 VAD 类型 │ ├─ [Section 内存] → 写原型 PTE → 更新段提交计数 │ ├─ [私有内存] → 更新 CommitCharge │ │ └─ 锁定工作集 │ │ └─ 遍历 PTE确保 PDE 有效写 DemandZero PTE │ └─ 解锁地址空间 │ └─ 返回 BaseAddress STATUS_SUCCESS3. NtFreeVirtualMemory——完整路径3.1 MEM_RELEASE 分支完整 VAD 释放四种释放情况情况1释放整个 VADBaseAddress VAD.StartingVpn, Size VAD 全范围 ─ 直接删除 VAD释放所有物理页 情况2释放 VAD 头部部分BaseAddress VAD.StartingVpn, Size VAD 全范围 ─ 调整 VAD.StartingVpn 原起始地址 Size ─ 释放对应 PTE 情况3释放 VAD 尾部部分BaseAddress VAD.StartingVpn, 释放到结束 ─ 调整 VAD.EndingVpn BaseAddress - 1 ─ 释放对应 PTE 情况4释放 VAD 中间部分释放中间一块两边保留 ─ 需要创建新 VAD 保存剩余后半部分 ─ 原 VAD 缩小到前半部分释放前 ┌──────────────────────────────┐ │ 原始 VAD │ └──────────────────────────────┘ 情况1 情况2 ┌──────────────────┐ ┌─────┐ ┌──────────┐ │ 全部释放 → 删除 │ │释放 │ │ 保留 │ └──────────────────┘ └─────┘ └──────────┘ Base StartingVpn 调整 情况3 情况4 ┌──────────┐ ┌─────┐ ┌─────┐ ┌──────┐ ┌─────┐ │ 保留 │ │释放 │ │释放 │ │ 保留1│ │保留2│ └──────────┘ └─────┘ └─────┘ └──────┘ └─────┘ (需要新建 VAD)3.2 MEM_DECOMMIT 分支取消提交// 1. 锁定地址空间// 2. 查找 VAD确认地址范围有效// 3. 调用 MiDecommitPages 取消提交// - 遍历指定范围的 PTE// - 对每个有效 PTE → 释放物理页、更新 PFN// - 将 PTE 写为 decommit 状态// 4. 更新进程 CommitCharge4. NtProtectVirtualMemory 路径通过MiProtectVirtualMemory实现1. 验证参数保护属性合法性 2. 锁定地址空间 3. 查找覆盖整个范围的 VAD 4. 调用 MiCheckSecuredVad 检查安全 VAD 限制 5. 锁定工作集 6. 遍历范围内的每个 PTE a. 如果 PTE 有效 - 修改硬件 PTE 的保护位 - 刷新 TLBKeFlushCurrentTb b. 如果 PTE 无效 - 修改软件 PTE 的保护位 c. 写时复制COW处理 - 如果新保护为只读但原为可写清除脏位 7. 更新 VAD 的保护属性 8. 解锁5. MiDeletePte——底层 PTE 删除逻辑文件virtual.c:369功能删除单个 PTE释放其引用的物理页。VOID NTAPIMiDeletePte(IN PMMPTE PointerPte,IN PVOID VirtualAddress,IN PEPROCESS CurrentProcess,IN PMMPTE PrototypePte){TempPte*PointerPte;if(TempPte.u.Hard.Valid0){// 无效 PTE可能是 Transition 或 PageFile 状态if(TempPte.u.Soft.Transition){// Transition PTE → 从列表中拆除递减引用MiUnlinkPageFromList(Pfn1);MiDecrementReferenceCount(Pfn1,PageFrameIndex);}// 忽略已换出PageFile的 PTE}else{// 有效 PTEPageFrameIndexPFN_FROM_PTE(TempPte);Pfn1MiGetPfnEntry(PageFrameIndex);if(Pfn1-u3.e1.PrototypePte1){// 原型 PTE → 递减页表共享计数和 PFN 共享计数MiDecrementShareCount(PageTablePfn,...);MiDecrementShareCount(Pfn1,PageFrameIndex);}else{// 普通 PTE → 标记删除递减共享计数MI_SET_PFN_DELETED(Pfn1);MiDecrementShareCount(Pfn1,PageFrameIndex);}// 擦除 PTEMI_ERASE_PTE(PointerPte);}KeFlushCurrentTb();}6. MiDeleteVirtualAddresses——批量 PTE 删除文件virtual.c:530功能批量删除指定虚拟地址范围内的所有 PTE。VOID NTAPIMiDeleteVirtualAddresses(IN ULONG_PTR Va,IN ULONG_PTR EndingAddress,IN OPTIONAL PMMVAD Vad){while(VaEndingAddress){// 逐级检查 PXE → PPE → PDE → PTE 的有效性// 跳过无效的大页表区域AddressGap// 对每个有效 PTE 调用 MiDeletePte// 递减页表引用计数必要时删除 PDEVaPAGE_SIZE;}}关键特点支持多级页表x86 PAE / x86-64的地址间隙跳过对 Section VAD 的间隙处理通过MI_GET_PROTOTYPE_PTE_FOR_VPN跳到下一个原型 PTE批量删除过程中保持 PFN 锁定7. MiDecommitPages——页面取消提交功能将已提交的页面取消提交释放物理内存但保留 VAD 结构。1. 遍历指定地址范围的每个 PTE 2. 对每个 PTE a. 如果 PTE 有效Valid1 - 获取 PFN - 标记 PFN 已删除MI_SET_PFN_DELETED - 递减 ShareCount - 擦除 PTE b. 如果 PTE 是 Transition 状态 - 从列表中拆除 PFN - 递减引用计数 c. 如果 PTE 是 DemandZero 状态 - 直接擦除 PTE 3. 更新进程/系统提交计数 4. 刷新 TLB8. MmGetPhysicalAddress——虚拟地址转物理地址文件virtual.c:5681PHYSICAL_ADDRESS NTAPIMmGetPhysicalAddress(PVOID Address){// 1. 检查 PDE 是否有效对大页 SPI 还检查 PPE/PXEif(MiAddressToPde(Address)-u.Hard.Valid){// 2. 检查是否为大页LargePageTempPde*MiAddressToPde(Address);if(TempPde.u.Hard.LargePage){// 大页偏移 地址低 22 位4MB 大页PhysicalAddress.QuadPart(ULONG64)TempPde.u.Hard.PageFrameNumberPAGE_SHIFT;PhysicalAddress.QuadPart((ULONG_PTR)Address(PAGE_SIZE*PTE_PER_PAGE-1));returnPhysicalAddress;}// 3. 检查 PTE 是否有效TempPte*MiAddressToPte(Address);if(TempPte.u.Hard.Valid){// 物理地址 PFN 12 页内偏移PhysicalAddress.QuadPart(ULONG64)TempPte.u.Hard.PageFrameNumberPAGE_SHIFT;PhysicalAddress.QuadPart((ULONG_PTR)Address(PAGE_SIZE-1));returnPhysicalAddress;}}// 4. 无效地址返回 0PhysicalAddress.QuadPart0;returnPhysicalAddress;}9. MmCopyVirtualMemory——跨进程内存拷贝文件virtual.c:1269两种策略基于数据量选择9.1 大拷贝 512 字节MDL 映射方式MiDoMappedCopyBufferSize MI_POOL_COPY_BYTES (512) → MiDoMappedCopy 流程 1. 循环拷贝每次最大 14 页MI_MAPPED_COPY_PAGES * PAGE_SIZE 56KB 2. 附加到源进程 → ProbeForRead → MmProbeAndLockPages → MmMapLockedPagesSpecifyCache 3. 分离源进程 4. 附加到目标进程 → ProbeForWrite → RtlCopyMemory 5. 分离目标进程 6. MmUnmapLockedPages → MmUnlockPages 7. 继续下一批数据9.2 小拷贝≤ 512 字节池缓冲方式MiDoPoolCopyBufferSize MI_POOL_COPY_BYTES (512) → MiDoPoolCopy 流程 1. 如果 BufferSize 512使用栈上缓冲StackBuffer否则分配 NonPagedPool 2. 附加到源进程 → ProbeForRead → RtlCopyMemory(池, 源) 3. 分离源进程 4. 附加到目标进程 → ProbeForWrite → RtlCopyMemory(目标, 池) 5. 分离目标进程 6. 重复直到所有数据拷贝完毕入口函数NTSTATUS NTAPIMmCopyVirtualMemory(PEPROCESS SourceProcess,PVOID SourceAddress,PEPROCESS TargetProcess,PVOID TargetAddress,SIZE_T BufferSize,KPROCESSOR_MODE PreviousMode,PSIZE_T ReturnSize){if(!BufferSize)returnSTATUS_SUCCESS;// 获取目标进程的 rundown protectionif(!ExAcquireRundownProtection(Process-RundownProtect))returnSTATUS_PROCESS_IS_TERMINATING;if(BufferSizeMI_POOL_COPY_BYTES)StatusMiDoMappedCopy(SourceProcess,SourceAddress,...);elseStatusMiDoPoolCopy(SourceProcess,SourceAddress,...);ExReleaseRundownProtection(Process-RundownProtect);returnStatus;}附录virtual.c 函数一览函数行号功能MiCalculatePageCommitment40计算指定地址范围内的已提交页数MiMakeSystemAddressValid181确保系统页表地址有效触发缺页MiDeleteSystemPageableVm273删除可分页系统内存MiDeletePte367删除单个 PTEMiDeleteVirtualAddresses528批量删除 PTEMiDoMappedCopy793MDL 方式跨进程拷贝MiDoPoolCopy1018池缓冲方式跨进程拷贝MmCopyVirtualMemory1269跨进程内存拷贝入口MiProtectVirtualMemory22 (extern)修改内存保护属性MiGetPageProtection1359获取页面的保护属性NtAllocateVirtualMemory4457虚拟内存分配系统调用MmGetPhysicalAddress5681虚拟地址→物理地址转换

相关新闻

【Claude Code】使用政策拒绝 Claude Code unable to respond Usage Policy refusal 应对

【Claude Code】使用政策拒绝 Claude Code unable to respond Usage Policy refusal 应对

文章目录 一、问题描述 1.1 环境信息 1.2 报错现象 二、根因分析 2.1 错误链路追踪 2.2 可能原因列举 三、解决方案 方案一:/rewind 回退到触发轮次之前(推荐) 方案二:/clear 启动全新会话 方案三:非交互模式(-p)的特殊处理 四、验证与回归测试 五、总结与预防 5.1 核心…

2026/7/22 22:30:14 阅读更多 →
07.20.每日总结

07.20.每日总结

7月20日总结 Linux基础 考试相关 复习前面讲过的所有命令 linux考试:91分 错题与不熟练的题: 存放了linux系统引导和启动时候使用的一些文件和目录的目录是/boot useradd添加用户时哪个选项可以指定描述信息-c 去掉vi编辑器中上一步错误的操作&#xff1…

2026/7/22 22:30:14 阅读更多 →
达梦数据库搭建(windows+Linux,图形化和命令行)

达梦数据库搭建(windows+Linux,图形化和命令行)

Windows上单机环境搭建Cmd命令systeminfo查看电脑信息确保1G可用内存根据电脑cpu和操作系统下载对应的数据库,并解压点击.iso光盘镜像文件安装选择时区并确定DM 数据库配置助手 来完成数据库初始化创建数据库实例选择数据库模板Linux上单机环境搭建获取对应的安装包…

2026/7/22 22:30:14 阅读更多 →

最新新闻

USB设备中断服务例程(ISR)设计:从原理到实战的嵌入式开发指南

USB设备中断服务例程(ISR)设计:从原理到实战的嵌入式开发指南

1. USB设备中断服务例程(ISR)的核心价值与设计挑战在嵌入式系统里做USB设备开发,中断服务例程(ISR)的设计绝对是整个固件架构的“心脏”。它直接决定了你的设备能否稳定、高效地与主机“对话”。很多刚接触USB协议栈的…

2026/7/22 23:54:24 阅读更多 →
提升.NET API安全性:Boxed.AspNetCore.Swagger认证授权最佳实践

提升.NET API安全性:Boxed.AspNetCore.Swagger认证授权最佳实践

提升.NET API安全性:Boxed.AspNetCore.Swagger认证授权最佳实践 【免费下载链接】Framework .NET Core Extensions and Helper NuGet packages. 项目地址: https://gitcode.com/gh_mirrors/framework8/Framework 在构建现代.NET API时,确保认证授…

2026/7/22 23:54:24 阅读更多 →
提示词权重分配全解析,深度解读Top 3企业级排序模型与AB测试验证数据

提示词权重分配全解析,深度解读Top 3企业级排序模型与AB测试验证数据

更多请点击: https://intelliparadigm.com 第一章:提示词权重分配全解析,深度解读Top 3企业级排序模型与AB测试验证数据 提示词权重分配是大模型应用落地的核心调控杠杆,直接影响生成质量、业务转化率与推理成本。企业级场景中&a…

2026/7/22 23:54:24 阅读更多 →
市场营销专业学生怎么做数据分析项目?

市场营销专业学生怎么做数据分析项目?

市场营销专业的学生想做数据分析项目,但常常不知道从哪下手。其实方向很明确——用户画像、投放复盘、竞品分析、品牌数据、活动效果分析,这五个场景就是最好的切入点。先看一组数据。字节跳动2026届校招中AI相关岗位占比65%以上,较2025届提升…

2026/7/22 23:54:24 阅读更多 →
模型漂移预警失效,搜索CTR骤降47%?——从日志到归因的AI搜索分析闭环(含可落地的Python诊断脚本)

模型漂移预警失效,搜索CTR骤降47%?——从日志到归因的AI搜索分析闭环(含可落地的Python诊断脚本)

更多请点击: https://intelliparadigm.com 第一章:模型漂移预警失效,搜索CTR骤降47%?——从日志到归因的AI搜索分析闭环(含可落地的Python诊断脚本) 当线上A/B测试未触发任何告警,而核心指标CT…

2026/7/22 23:54:24 阅读更多 →
从0到1掌握MultipleStatusView:新手友好的Android多状态视图组件教程

从0到1掌握MultipleStatusView:新手友好的Android多状态视图组件教程

从0到1掌握MultipleStatusView:新手友好的Android多状态视图组件教程 【免费下载链接】MultipleStatusView 一个支持多种状态的自定义View,可以方便的切换到:加载中视图、错误视图、空数据视图、网络异常视图、内容视图。 项目地址: https://gitcode.c…

2026/7/22 23:53:24 阅读更多 →

日新闻

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

1. 项目概述与SYSCFG模块的核心价值在嵌入式系统,尤其是像TI C6000系列这样的高性能DSP开发中,我们常常会与芯片手册里那些密密麻麻的寄存器打交道。很多开发者可能更关注算法实现、内存优化或者外设驱动,但对于一个稳定、高效的系统而言&…

2026/7/22 0:00:26 阅读更多 →
微信Server酱:高到达率的应急通知方案实践

微信Server酱:高到达率的应急通知方案实践

1. 为什么我们需要"最次"的通知方案? 在数字化协作环境中,消息通知系统的重要性不言而喻明。但现实情况是,企业级通知方案往往需要复杂的API对接(如企业微信、钉钉、飞书),个人开发者的小项目又经…

2026/7/22 0:00:26 阅读更多 →
甲方要的“简洁“PPT,到底是简洁还是省事?

甲方要的“简洁“PPT,到底是简洁还是省事?

甲方说"简洁一点",乙方听到的是"少做几页"。甲方说"不要太复杂",乙方理解成"别放图表了"。结果交过去,甲方说"我说的简洁不是这个意思"。"简洁"这个词在PPT语境里,是…

2026/7/22 0:00:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 12:54:44 阅读更多 →

月新闻