You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何整合PROCESS_MEMORY_COUNTERS_EX结构体返回的进程内存信息?

嘿,这个问题我之前做Windows进程监控的时候也碰到过——PROCESS_MEMORY_COUNTERS_EX确实把内存数据拆得很细碎,不过只要按照内存的不同属性归类,再做些格式化转换,就能把这些零散的数据变成清晰有用的信息。下面我分享几个实用的处理思路和代码示例:

1. 按内存类型归类整理

先把结构体里的字段按内存维度分组,这样能快速理清不同类别的内存占用情况:

  • 工作集内存(Working Set):进程当前实际加载到物理内存中的部分,包含共享和私有内容
    • PeakWorkingSetSize:工作集内存的历史峰值
    • WorkingSetSize:当前工作集内存大小
  • 系统内核池内存:进程向系统内核申请的内存资源
    • 分页池:QuotaPeakPagedPoolUsage(峰值)、QuotaPagedPoolUsage(当前)——可被交换到页文件的内核内存
    • 非分页池:QuotaPeakNonPagedPoolUsage(峰值)、QuotaNonPagedPoolUsage(当前)——必须留在物理内存的内核内存
  • 虚拟/私有内存:进程独占的虚拟内存空间(包括物理内存和页文件中的部分)
    • PagefileUsage:当前进程占用的页文件大小
    • PeakPagefileUsage:页文件使用的历史峰值
    • PrivateUsage:进程独占的内存大小(这是日常排查内存泄漏时最常用的指标之一)
2. 把字节数转换成易读的单位

结构体返回的所有SIZE_T字段都是字节数,直接看数字太不直观,写个小工具函数把字节转换成带单位的字符串:

#include <string>
#include <cmath>
#include <cstdio>

std::string FormatMemorySize(SIZE_T bytes) {
    const char* units[] = {"B", "KB", "MB", "GB", "TB"};
    int unitIndex = 0;
    double size = static_cast<double>(bytes);
    
    // 按1024进制转换单位
    while (size >= 1024 && unitIndex < 4) {
        size /= 1024;
        unitIndex++;
    }
    
    char buffer[64];
    snprintf(buffer, sizeof(buffer), "%.2f %s", size, units[unitIndex]);
    return std::string(buffer);
}

调用这个函数,比如FormatMemorySize(pmce.PrivateUsage),就能得到类似"185.60 MB"的友好结果。

3. 封装成可复用的工具函数/结构体

把获取和处理的逻辑封装起来,以后需要获取进程内存信息时直接调用就行,不用重复写代码:

#include <windows.h>
#include <psapi.h>
#include <string>

// 链接PSAPI库,VS环境下可以加这个编译指令
#pragma comment(lib, "psapi.lib")

// 整理后的内存信息结构体
struct ProcessMemoryStats {
    std::string workingSetCurrent;
    std::string workingSetPeak;
    std::string pagedPoolCurrent;
    std::string pagedPoolPeak;
    std::string nonPagedPoolCurrent;
    std::string nonPagedPoolPeak;
    std::string pagefileCurrent;
    std::string pagefilePeak;
    std::string privateUsage;
};

ProcessMemoryStats GetProcessMemoryStats(DWORD processId) {
    ProcessMemoryStats stats;
    // 打开进程,需要查询信息和读取内存的权限
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
    if (!hProcess) {
        return stats;
    }
    
    PROCESS_MEMORY_COUNTERS_EX pmce;
    pmce.cb = sizeof(PROCESS_MEMORY_COUNTERS_EX);
    if (GetProcessMemoryInfo(hProcess, reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmce), pmce.cb)) {
        // 把每个字段转换成易读的格式
        stats.workingSetCurrent = FormatMemorySize(pmce.WorkingSetSize);
        stats.workingSetPeak = FormatMemorySize(pmce.PeakWorkingSetSize);
        stats.pagedPoolCurrent = FormatMemorySize(pmce.QuotaPagedPoolUsage);
        stats.pagedPoolPeak = FormatMemorySize(pmce.QuotaPeakPagedPoolUsage);
        stats.nonPagedPoolCurrent = FormatMemorySize(pmce.QuotaNonPagedPoolUsage);
        stats.nonPagedPoolPeak = FormatMemorySize(pmce.QuotaPeakNonPagedPoolUsage);
        stats.pagefileCurrent = FormatMemorySize(pmce.PagefileUsage);
        stats.pagefilePeak = FormatMemorySize(pmce.PeakPagefileUsage);
        stats.privateUsage = FormatMemorySize(pmce.PrivateUsage);
    }
    
    CloseHandle(hProcess);
    return stats;
}

比如要获取当前进程的内存信息,直接调用GetProcessMemoryStats(GetCurrentProcessId())就行。

4. 格式化输出,让数据一目了然

拿到整理后的信息后,可以输出成清晰的格式,比如在控制台打印:

void PrintProcessMemoryStats(const ProcessMemoryStats& stats) {
    printf("=== 进程内存统计信息 ===\n");
    printf("工作集内存:当前 %s | 峰值 %s\n", stats.workingSetCurrent.c_str(), stats.workingSetPeak.c_str());
    printf("分页池内存:当前 %s | 峰值 %s\n", stats.pagedPoolCurrent.c_str(), stats.pagedPoolPeak.c_str());
    printf("非分页池内存:当前 %s | 峰值 %s\n", stats.nonPagedPoolCurrent.c_str(), stats.nonPagedPoolPeak.c_str());
    printf("页文件使用:当前 %s | 峰值 %s\n", stats.pagefileCurrent.c_str(), stats.pagefilePeak.c_str());
    printf("私有内存:%s\n", stats.privateUsage.c_str());
}

输出的结果会非常直观:

=== 进程内存统计信息 ===
工作集内存:当前 128.50 MB | 峰值 156.20 MB
分页池内存:当前 2.30 MB | 峰值 2.50 MB
非分页池内存:当前 1.10 MB | 峰值 1.20 MB
页文件使用:当前 200.40 MB | 峰值 220.10 MB
私有内存:180.30 MB

最后提个小注意点:调用OpenProcess时需要确保有足够的权限,如果是获取系统进程的内存信息,可能需要以管理员身份运行程序。

内容的提问来源于stack exchange,提问作者user7847018

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:10:42