# 系统内存审计

KSword 的“内存 -> 系统内存审计”页用于回答“物理内存到底被什么占用”，而不是只把普通进程工作集相加。它参考 PoolMonXv3 的池标签增量思路，并把采集面扩展为整机物理分布、用户态驻留及其文件/映像关系、内核进程快照、Pool Tag 和 Big Pool。

## 数据面

- 安装边界：`GetPhysicallyInstalledSystemMemory` 给出安装 RAM；它与 Windows 可用物理内存之间的差值单列为“硬件/固件保留”。安装 RAM 会先被完整分成硬件/固件保留和 Windows 可用两部分。
- 物理边界：`SystemMemoryUsageInformation`、`GlobalMemoryStatusEx` 和 `GetPerformanceInfo` 给出 Windows 可用物理总量、可用量、在用量与提交量。
- 页面状态：`SystemMemoryListInformation` 将可用页拆成 0-7 优先级 Standby、Free、Zeroed，并单列仍占用 RAM 的 Modified、Modified No-Write 与 Bad pages。
- 用户态驻留：后台深度扫描使用 `QueryWorkingSet`、`VirtualQueryEx` 和 `GetMappedFileNameW`，按“进程 + 私有分配/映像/映射文件/页文件节 + 后备文件”建立驻留关系。它显示驻留引用、私有驻留、可共享引用、实际共享引用，以及按系统报告共享计数折算的比例估算。
- 进程：`SystemProcessInformation` 直接使用内核快照，展示私有驻留、工作集引用、私有提交、池配额和硬缺页。私有驻留可以相加；工作集中的共享部分不可直接相加。
- 内核池：`SystemPoolTagInformation` 按四字节 tag 展示 paged/nonpaged 字节、未释放分配数和相邻快照增量。若安装 Windows Debugging Tools，会从 `pooltag.txt` 补充来源和描述。
- 大块分配：`SystemBigPoolInformation` 展示逐项地址、大小、tag 和 paged/nonpaged 属性。Big Pool 已包含在 pool 总量中，不得重复相加。
- 内核常驻：`SystemPerformanceInformation` 提供 nonpaged pool、paged pool resident、system code、driver code 与 system cache resident；新系统还可能提供 MDL、PFN database、system page tables 和 contiguous pages 证据。

“用户态驻留”扫描在页面打开和手工点击“深度扫描用户态驻留”时运行；2 秒自动刷新只更新轻量级整机快照，不反复遍历所有进程。状态栏会显示可访问进程数。PPL、权限受限或正在退出的进程会保留在覆盖率分母中，而不会被伪装成已经归因。

## 为什么共享页不能强行指定一个唯一进程

同一个物理页可以同时出现在多个进程工作集中，也可以由映像、映射文件、系统文件缓存或内核共同引用。Windows 工作集接口提供的共享计数最大只表示到 7，因此“比例估算”适合解释关系和规模，不是逐 PFN 的精确去重总量。

本页采用“真实所有者关系图”而不是伪造单一所有者：私有页归到进程；映像/文件页同时保留进程引用者和后备文件；共享引用单列且明确不可相加；无法由稳定接口公开唯一关系的部分保留在“未归因在用余量”。这样安装 RAM 的顶层边界可以闭合，同时不会把一个共享页重复算给多个进程后声称达成虚假的 100%。

## “未归因在用余量”是什么意思

页面只把可安全相加、不明显重叠的驻留类别计入“已识别下限”：进程私有驻留、nonpaged pool、paged pool resident、内核/驱动代码常驻和 modified page lists。`在用物理内存 - 已识别下限` 会作为“未归因在用余量”保留。

该余量不是错误，也不等于泄漏。它可能包含共享或映像页、进程/系统页表、内核栈、MDL 锁页、AWE/大页、内存压缩存储、VBS/Hyper-V 安全内存，以及硬件或设备相关的不可见占用。保留余量可以避免把重叠的 cache、shared working set、Big Pool 或提交量重复相加后得到虚假的 100% 归因。

## 排查顺序

1. 先看“在用”和“未归因在用余量”的增量，确认问题是持续增长还是一次性缓存变化。
2. 执行“深度扫描用户态驻留”，按比例估算或私有驻留排序，查看进程、映像、映射文件和页文件节的真实关系；同时检查可访问进程覆盖率。
3. 看“内核进程快照”的私有驻留增量，定位用户态、受保护进程、System/压缩存储方向。
4. 看“Pool Tags”的 nonpaged、paged 与 outstanding 增量；tag 只是一条归因证据，不能仅凭名字认定驱动所有权。
5. 看“Big Pool”确认大块、不可分页的具体分配和地址是否持续出现。
6. 若余量仍持续增长，用 WPR/WPA Memory Footprint/Reference Set 记录时间因果；稳定的 R3 快照接口并不公开每个 PFN 的唯一当前所有者。

## 技术参考

- PoolMonXv3：池标签聚合、增量与来源说明的交互思路。
- System Informer：虚拟内存区域、工作集页属性、映像/映射文件路径与共享驻留的实现参考。
- MemProcFS：PFN 数据库视角，以及私有进程页、文件页、共享页并非都具有一个 PID 所有者的表达方式。
- Windows Performance Toolkit：Memory Footprint 和 Reference Set 用于按场景/时间窗口补充快照无法表达的因果关系。

本页只读，不清理 Standby、不触发 trim、不修改 pool，也不扫描或导出物理内存内容。
