【问题标题】:GlobalMemoryStatusEx/GetPerformanceInfo - Getting Actual Page File size, used page file and available page fileGlobalMemoryStatusEx/GetPerformanceInfo - 获取实际页面文件大小、使用的页面文件和可用的页面文件
【发布时间】:2017-06-20 09:43:45
【问题描述】:

基于以下链接:MSDN Docu

我正在尝试获取当前正在使用的页面文件的大小。

这是我获取值的方式:

ActualPageFileSize = ullAvailPageFile - ullTotalPageFile
AvailablePageFileSize = ullAvailPageFile - ullAvailPhys
UsedPageFile = ActualPageFileSize - AvailablePageFileSize

以上计算基于另一篇文章: Another post

我现在遇到的问题是,有时 AvailablePageFileSize 的值大于 ActualPageFileSize 的值,因此返回 UsedPageFile 的负值。

你们中有人遇到过吗?任何想法将不胜感激。

提前谢谢你!

附言

示例代码:

#define DIV 1024

void _tmain()
{
  MEMORYSTATUSEX statex;

  statex.dwLength = sizeof (statex);

  GlobalMemoryStatusEx (&statex);

    double committedBytes = 1;

    _tprintf (TEXT("==================================================\n"));
    _tprintf (TEXT("GlobalMemoryStatusEx\n"));
    _tprintf (TEXT("==================================================\n"));
    _tprintf (TEXT("           %PhysUsed : %ld\n"), statex.dwMemoryLoad);
    _tprintf (TEXT("        ullTotalPhys : %I64d (%I64d MB)\n"), statex.ullTotalPhys, statex.ullTotalPhys / (DIV*DIV));
    _tprintf (TEXT("        ullAvailPhys : %I64d (%I64d MB)\n"), statex.ullAvailPhys, statex.ullAvailPhys / (DIV*DIV));
    _tprintf (TEXT("         ullUsedPhys : %I64d (%I64d MB)\n"), statex.ullTotalPhys - statex.ullAvailPhys, (statex.ullTotalPhys - statex.ullAvailPhys) / (DIV*DIV));
    _tprintf (TEXT("                       --------------------------\n"));
    _tprintf (TEXT("   Phys Avail + Used = %I64d (%I64d MB)\n"), statex.ullAvailPhys + (statex.ullTotalPhys - statex.ullAvailPhys), (statex.ullAvailPhys + (statex.ullTotalPhys - statex.ullAvailPhys)) / (DIV*DIV));

    _tprintf (TEXT("==================================================\n"));
    _tprintf (TEXT("    ullTotalPageFile : %I64d (%I64d MB)\n"), statex.ullTotalPageFile, statex.ullTotalPageFile / (DIV*DIV));
    _tprintf (TEXT("    ullAvailPageFile : %I64d (%I64d MB)\n"), statex.ullAvailPageFile, statex.ullAvailPageFile / (DIV*DIV));
    _tprintf (TEXT("     ullUsedPageFile : %I64d (%I64d MB)\n"), statex.ullTotalPageFile - statex.ullAvailPageFile, (statex.ullTotalPageFile - statex.ullAvailPageFile) / (DIV*DIV));
    _tprintf (TEXT("                       --------------------------\n"));
    _tprintf (TEXT("   Page Avail + Used = %I64d (%I64d MB)\n"), statex.ullAvailPageFile + (statex.ullTotalPageFile - statex.ullAvailPageFile), (statex.ullAvailPageFile + (statex.ullTotalPageFile - statex.ullAvailPageFile)) / (DIV*DIV));

    _tprintf (TEXT("==================================================\n"));
    _tprintf (TEXT(" ActualTotalPageFile : %I64d (%I64d MB)\n"), statex.ullTotalPageFile - statex.ullTotalPhys, (statex.ullTotalPageFile - statex.ullTotalPhys) / (DIV*DIV));
    _tprintf (TEXT(" ActualAvailPageFile : %I64d (%I64d MB)\n"), statex.ullAvailPageFile - statex.ullAvailPhys, (statex.ullAvailPageFile - statex.ullAvailPhys) / (DIV*DIV));
    _tprintf (TEXT("  ActualPageFileUsed : %I64d (%I64d MB)\n"), (statex.ullTotalPageFile - statex.ullTotalPhys) - (statex.ullAvailPageFile - statex.ullAvailPhys), ((statex.ullTotalPageFile - statex.ullTotalPhys) - (statex.ullAvailPageFile - statex.ullAvailPhys)) / (DIV*DIV));
    _tprintf (TEXT("            Variance : %I64d (%I64d MB)\n"), (statex.ullAvailPageFile - statex.ullAvailPhys) - (statex.ullTotalPageFile - statex.ullTotalPhys), ((statex.ullAvailPageFile - statex.ullAvailPhys) - (statex.ullTotalPageFile - statex.ullTotalPhys)) / (DIV*DIV));
    _tprintf (TEXT("                       --------------------------\n"));
    _tprintf (TEXT("ActPage Avail + Used = %I64d (%I64d MB)\n"), (statex.ullAvailPageFile - statex.ullAvailPhys) + ((statex.ullTotalPageFile - statex.ullTotalPhys) - (statex.ullAvailPageFile - statex.ullAvailPhys)), ((statex.ullAvailPageFile - statex.ullAvailPhys) + ((statex.ullTotalPageFile - statex.ullTotalPhys) - (statex.ullAvailPageFile - statex.ullAvailPhys))) / (DIV*DIV));
    _tprintf (TEXT("==================================================\n"));
    _tprintf (TEXT("     ullTotalVirtual : %I64d (%I64d MB)\n"), statex.ullTotalVirtual, statex.ullTotalVirtual / (DIV*DIV));
    _tprintf (TEXT("     ullAvailVirtual : %I64d (%I64d MB)\n"), statex.ullAvailVirtual, statex.ullAvailVirtual / (DIV*DIV));
    _tprintf (TEXT(" ullAvailVirtualUsed : %I64d (%I64d MB)\n"), statex.ullTotalVirtual - statex.ullAvailVirtual, (statex.ullTotalVirtual - statex.ullAvailVirtual) / (DIV*DIV));


    PERFORMACE_INFORMATION perfInfo;
    int ret;

    ret = GetPerformanceInfo (&perfInfo,sizeof(perfInfo));

    _tprintf (TEXT("==================================================\n"));
    _tprintf (TEXT("GetPerformanceInfo\n"));
    _tprintf (TEXT("==================================================\n"));

    _tprintf (TEXT("       PageSize : %d (%d MB) \n"), perfInfo.PageSize, perfInfo.PageSize / DIV);
    _tprintf (TEXT("    CommitTotal : %d (%d MB) X %d = %I64d (%I64d MB)\n"), perfInfo.CommitTotal, perfInfo.CommitTotal / DIV, perfInfo.PageSize, (DWORDLONG)perfInfo.CommitTotal * perfInfo.PageSize, (DWORDLONG)(perfInfo.CommitTotal * perfInfo.PageSize)  / (DIV*DIV));
    _tprintf (TEXT("    CommitLimit : %d (%d MB) X %d = %I64d (%I64d MB)\n"), perfInfo.CommitLimit, perfInfo.CommitLimit / DIV, perfInfo.PageSize, (DWORDLONG)perfInfo.CommitLimit * perfInfo.PageSize, (DWORDLONG)(perfInfo.CommitLimit * perfInfo.PageSize) / (DIV*DIV));
    _tprintf (TEXT("    CommitAvail : %d (%d MB) X %d = %I64d (%I64d MB)\n"), perfInfo.CommitLimit - perfInfo.CommitTotal, (perfInfo.CommitLimit - perfInfo.CommitTotal) / DIV, perfInfo.PageSize, (DWORDLONG)(perfInfo.CommitLimit - perfInfo.CommitTotal) * perfInfo.PageSize, (DWORDLONG)((perfInfo.CommitLimit - perfInfo.CommitTotal) * perfInfo.PageSize) / (DIV*DIV));
    _tprintf (TEXT("  PhysicalTotal : %d (%d MB) X %d = %I64d (%I64d MB)\n"), perfInfo.PhysicalTotal, perfInfo.PhysicalTotal / DIV, perfInfo.PageSize, (DWORDLONG)perfInfo.PhysicalTotal * perfInfo.PageSize, (DWORDLONG)(perfInfo.PhysicalTotal * perfInfo.PageSize) / (DIV*DIV));
    _tprintf (TEXT("  PhysicalAvail : %d (%d MB) X %d = %I64d (%I64d MB)\n"), perfInfo.PhysicalAvailable, perfInfo.PhysicalAvailable / DIV, perfInfo.PageSize, (DWORDLONG)(perfInfo.PhysicalAvailable * perfInfo.PageSize), (DWORDLONG)(perfInfo.PhysicalAvailable * perfInfo.PageSize) / (DIV*DIV));

    DWORDLONG ptotal = (DWORDLONG)(perfInfo.CommitLimit - perfInfo.PhysicalTotal) * perfInfo.PageSize;
    DWORDLONG pavail = (DWORDLONG)((perfInfo.CommitLimit - perfInfo.CommitTotal) - perfInfo.PhysicalAvailable) * perfInfo.PageSize;
    _tprintf (TEXT("\nCommitLimit - PhysicalTotal = %I64d (%I64d MB) \n"), ptotal, (DWORDLONG)ptotal / (DIV*DIV));
    _tprintf (TEXT("CommitAvail - PhysicalAvail = %I64d (%I64d MB) \n"), pavail, (DWORDLONG)pavail / (DIV*DIV));
    _tprintf (TEXT("CommitUsed  - %I64d (%I64d MB) \n"), (DWORDLONG)(ptotal - pavail), (DWORDLONG)(ptotal - pavail) / (DIV*DIV));
}

样品良好的输出:

R:\>memtest.exe
==================================================
GlobalMemoryStatusEx
==================================================
           PhysUsed : 24
        ullTotalPhys : 4294430720 (4095 MB)
        ullAvailPhys : 3231776768 (3082 MB)
         ullUsedPhys : 1062653952 (1013 MB)
                       --------------------------
   Phys Avail + Used = 4294430720 (4095 MB)
==================================================
    ullTotalPageFile : 5032628224 (4799 MB)
    ullAvailPageFile : 3932905472 (3750 MB)
     ullUsedPageFile : 1099722752 (1048 MB)
                       --------------------------
   Page Avail + Used = 5032628224 (4799 MB)
==================================================
 ActualTotalPageFile : 738197504 (704 MB)
 ActualAvailPageFile : 701128704 (668 MB)
  ActualPageFileUsed : 37068800 (35 MB)
            Variance : -37068800 (17592186044380 MB)
                       --------------------------
ActPage Avail + Used = 738197504 (704 MB)
==================================================
     ullTotalVirtual : 2147352576 (2047 MB)
     ullAvailVirtual : 2072608768 (1976 MB)
 ullAvailVirtualUsed : 74743808 (71 MB)
==================================================
GetPerformanceInfo
==================================================
       PageSize : 4096 (4 MB)
    CommitTotal : 268487 (262 MB) X 4096 = 1099722752 (1048 MB)
    CommitLimit : 1228669 (1199 MB) X 4096 = 5032628224 (703 MB)
    CommitAvail : 960182 (937 MB) X 4096 = 3932905472 (3750 MB)
  PhysicalTotal : 1048445 (1023 MB) X 4096 = 4294430720 (4095 MB)
  PhysicalAvail : 789000 (770 MB) X 4096 = 3231744000 (3082 MB)

CommitLimit - PhysicalTotal = 738197504 (704 MB)
CommitAvail - PhysicalAvail = 701161472 (668 MB)
CommitUsed  - 37036032 (35 MB)

R:\>

样本错误输出:

U:\>memtest.exe
==================================================
GlobalMemoryStatusEx
==================================================
           PhysUsed : 35
        ullTotalPhys : 3220688896 (3071 MB)
        ullAvailPhys : 2087751680 (1991 MB) <--- Should be less than ullAvailPageFile
         ullUsedPhys : 1132937216 (1080 MB)
                       --------------------------
   Phys Avail + Used = 3220688896 (3071 MB)
==================================================
    ullTotalPageFile : 3757559808 (3583 MB)
    ullAvailPageFile : 1925316608 (1836 MB) <-- Shouldbe greater than ullAvailPhys
     ullUsedPageFile : 1832243200 (1747 MB)
                       --------------------------
   Page Avail + Used = 3757559808 (3583 MB)
==================================================
 ActualTotalPageFile : 536870912 (512 MB)
 ActualAvailPageFile : -162435072 (17592186044261 MB) <-- This is ullAvailPageFile - ullAvailPhys
  ActualPageFileUsed : 699305984 (666 MB)
            Variance : -699305984 (17592186043749 MB)
                       --------------------------
ActPage Avail + Used = 536870912 (512 MB)
==================================================
     ullTotalVirtual : 2147352576 (2047 MB)
     ullAvailVirtual : 2139230208 (2040 MB)
 ullAvailVirtualUsed : 8122368 (7 MB)
==================================================
GetPerformanceInfo
==================================================
       PageSize : 4096 (4 MB)
    CommitTotal : 447325 (436 MB) X 4096 = 1832243200 (1747 MB)
    CommitLimit : 917373 (895 MB) X 4096 = 3757559808 (3583 MB)
    CommitAvail : 470048 (459 MB) X 4096 = 1925316608 (1836 MB)
  PhysicalTotal : 786301 (767 MB) X 4096 = 3220688896 (3071 MB)
  PhysicalAvail : 509698 (497 MB) X 4096 = 2087723008 (1991 MB)

CommitLimit - PhysicalTotal = 536870912 (512 MB)
CommitAvail - PhysicalAvail = 17592023638016 (16777061 MB)
CommitUsed  - -17591486767104 (17592169267866 MB)

U:\>

【问题讨论】:

  • 问答编辑器右上角有一个帮助链接。它解释了降价编辑工具。阅读并修复您的格式。此外,强烈建议提供minimal reproducible example
  • “应该”的断言根本不正确。分页文件大小受配置影响,并随着提交的内存需求的变化而动态变化。如果您想了解这些数字的含义,则需要阅读 Russinovich 的“Windows Internals”。使用性能计数器或 WMI 获取实际的分页文件和内存使用统计信息,使用 Perfmon.exe 进行查看。
  • 如果你想得到系统中分页文件的信息——调用NtQuerySystemInformation(SystemPageFileInformation,..——你得到了关于这个SYSTEM_PAGEFILE_INFORMATION的完整信息
  • @Hans Passant 如果您从 ullTotalPageFile 中减去 ullTotalPhys,您将获得系统中配置的实际页面文件大小。 WMI 返回相同的值。根据 resmon 和 perfmon 确认,事物的物理内存方面也是正确的。我知道这些值发生了变化,但我计算的值是一次 winapi 调用的结果。如您所见,对 GlobalMemoryStatusEx 和 GetPerformanceInfo 的调用返回值相似。
  • @RbMm 我将尝试实现此代码还原并返回结果。谢谢

标签: windows winapi pagefile


【解决方案1】:

下一个代码从 win2000 到最新的 win10 x64 的最低限度。关于已弃用、未记录等:

NtQuerySystemInformation 将来可能会更改或不可用 Windows 版本。

我已经读了大约 15 年了。 ntdll api 将来会/可以被删除 - 我个人的选择是不。绝不。这是基本的原生 api 和基于此的所有所谓的 win32 api。但这只是我的选择。刚才这在所有现有的 Windows 版本上都很好用。照原样(我相信这也将在新版本中起作用)

typedef struct SYSTEM_PAGEFILE_INFORMATION
{
    ULONG NextEntryOffset;
    ULONG TotalSize;
    ULONG TotalInUse;
    ULONG PeakUsage;
    UNICODE_STRING PageFileName;
} *PSYSTEM_PAGEFILE_INFORMATION;

NTSTATUS GetPageFilesInfo()
{
    static volatile UCHAR guz;
    PVOID stack = alloca(guz);
    ULONG cb = 0, rcb = 2*sizeof(SYSTEM_PAGEFILE_INFORMATION) + 64* sizeof(WCHAR);

    union {
        PVOID buf;
        PSYSTEM_PAGEFILE_INFORMATION pspfi;
        PBYTE pb;
    };
    NTSTATUS status;
    do 
    {
        if (cb < rcb)
        {
            cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
        }

        if (0 <= (status = NtQuerySystemInformation(SystemPageFileInformation, buf, cb, &rcb)))
        {
            ULONG NextEntryOffset = 0;
            do 
            {
                pb += NextEntryOffset;

                DbgPrint("%ukb %ukb %ukb %wZ\n", pspfi->TotalInUse, pspfi->PeakUsage, pspfi->TotalSize, &pspfi->PageFileName);

            } while (NextEntryOffset = pspfi->NextEntryOffset);

            break;
        }

    } while (status == STATUS_INFO_LENGTH_MISMATCH);

    return status;
}

如果打开ZwQuerySystemInformation的页面很有趣

[ZwQuerySystemInformation 不再可用 视窗 8。相反,请使用此处列出的替代功能 话题。]

但这是直接的谎言 - ZwQuerySystemInformation 可用并且在 win 8、win 8.1、win 10.. 和 用户模式 Zw 和 Nt 函数 - 这是别名 - 它总是指向相同地址(这是具有 2 个名称的单个函数)

【讨论】:

  • TotalInUsePeakUsageTotalSize 以 killo 字节为单位,而不是以字节为单位。 - 所以在 4096 或 0x1000 字节中
  • 你能提供你使用的标题吗?我似乎找不到 UNICODE_STRING 和 NTSTATUS 的定义
  • 我也一直在尝试查找 SystemPageFileInformation。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
  • 1970-01-01
  • 2013-01-13
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 2013-11-26
相关资源
最近更新 更多