简体   繁体   中英

GlobalMemoryStatusEx/GetPerformanceInfo - Getting Actual Page File size, used page file and available page file

Based on the following link: MSDN Docu

I am trying to get the size of the page file that is currently being used.

Here's how I am getting the values:

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

Above computation is based on another post: Another post

The issue that I am having right now is that sometimes the value of AvailablePageFileSize is greater than the value of ActualPageFileSize, hence returning a negative value for the UsedPageFile.

Have any of you encountered this? Any idea will be greatly appreciated.

Thank you in advance!

PS

Sample code:

#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));
}

Sample Good Output:

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:\>

Sample Bad Output:

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:\>

the next code worked how minimum from win2000 up to the latest win10 x64. about deprecated, undocumented, etc:

NtQuerySystemInformation may be altered or unavailable in future versions of Windows.

i read this already ~15 years. are ntdll api will be/can be removed in future - my personal option that no. never. this is base native api and all so called win32 api based on this. but this is only my option. how minimum just now this is fine worked on all existing windows versions. as is (i sure that will be worked and on new builds too)

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;
}

funny that if open page for ZwQuerySystemInformation

[ZwQuerySystemInformation is no longer available for use as of Windows 8 . Instead, use the alternate functions listed in this topic.]

but this is direct lie - ZwQuerySystemInformation available and in win 8, win 8.1, win 10.. and in user mode Zw and Nt functions - this is aliases - it always point to same address (this is single function with 2 names)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM