• 第14章 探索虚拟内存(1)


    14.1 系统信息

    (1)获取系统信息GetSystemInfo函数中的SYSTEM_INFO参数

    字段

    描述

    WORD wProcessorArchitecture或

    wReserved

    联合体。为今后扩展而保留,请勿使用

    DWORD dwPageSize

    表示CPU页面的大小。在x86和x64机器中,该值为4KB(4096字节),在IA-64机器中,该值为8K字节(8192字节)

    LPVOID lpMinimumApplicationAddress

    给出每个进程可用地址空间中最小的内存地址。由于每个进程的地址空间中最开始的64KB始终是空闲的,因此该值为65536或0x0000 1000。

    LPVOID lpMaximumApplicationAddress

    给出每个进程的么有地址空间中最大的可用内存地址

    DWORD_PTR dwActiveProcessorMask

    一个位掩码,用来表示哪些CPU处于活动状态(即可以用来运行线程)

    DWORD dwNumberOfProcessors

    表示机器中CPU的数量。双核处理器时该值为2。

    DWORD dwProcessorType

    己经作废,请勿使用

    DWORD dwAllocationGranularity

    表示用于预订地址空间区域的分配粒度。该值在Windows平台上都是65536.即64K。即区域的起始地址必须是64KB的整数倍

    WORD wProcessorLevel

    进一步细分处理器的体系结构。如表示Intel奔腾III或奔腾IV。如果需要确定CPU支持哪些特性,可以调用

    IsProcessorFeaturePresent函数,而不是使用这个字段。

    WORD wProcessorRevision

    进一步对wProcessorLevel进行细分。

    (2)IsWow64Process:判断进程是否运行在WOW64环境下,即是否在64位操作系统上运行32位的应用程序。类似于旧的 WOW32 子系统,负责在 Windows 32 位版本下运行 16 位的代码。

    参数

    描述

    HANDLE hProcess

    要判断的进程句柄

    PBOOL pbWow64Process

    TRUE:32位应用程序运行在64位操作系统上

    FALSE:32位应用程序运行在32位操作系统或64位应用程序运行在64位的操作系统上。

    返回值

    FALSE:最常见的原因是传效的参数无效。

    TRUE:函数调用成功

    备注:

    ①32位应用程序运行在64位操作系统时,GetSystemInfo得到的dwPageSize为4KB,这种情况下,为了获得64位操作系统实际的系统信息,可以调用GetNativeSystemInfo函数。

    ②64位应用程序运行在64位操作系统时,GetSystemInfo得到的dwPageSize为8KB。

    【SysInfo程序】获取系统信息

    /*************************************************************************
    Module: SysInfo.cpp
    Notices:Copyright(c) 2008 Jeffrey Richter & Christophe Nasarre
    *************************************************************************/
    
    #include "../../CommonFiles/CmnHdr.h"
    #include "resource.h"
    #include <tchar.h>
    #include <strsafe.h>
    
    //////////////////////////////////////////////////////////////////////////
    //将数据转为字符,并用逗号分开
    PTSTR BigNumToString(LONG lNum, PTSTR szBuf, DWORD chBufSize){
        TCHAR szNum[100];
        StringCchPrintf(szNum, _countof(szNum), TEXT("%d"), lNum);
        NUMBERFMT nf;
        nf.NumDigits = 0;
        nf.LeadingZero = FALSE;
        nf.Grouping = 3;//每3位一组
        nf.lpDecimalSep = TEXT(".");
        nf.lpThousandSep = TEXT(",");
        nf.NegativeOrder = 0;
        GetNumberFormat(LOCALE_USER_DEFAULT, 0, szNum, &nf, szBuf, chBufSize);
        return(szBuf);
    }
    
    //////////////////////////////////////////////////////////////////////////
    //显示对话框标题
    void ShowBitness(HWND hwnd){
        TCHAR szFullTitle[100];
        TCHAR szTitle[32];
        GetWindowText(hwnd, szTitle, _countof(szTitle));
    
    #if defined(_WIN64)
        //64位的应用程序只能运行在64位的操作系统上
        //因此,这里不需要特殊的检查
        StringCchPrintf(szFullTitle, _countof(szFullTitle), TEXT("64位'%s'"), szTitle);
    #else
        BOOL bIsWow64 = FALSE;
        if (!IsWow64Process(GetCurrentProcess(),&bIsWow64)){
            chFAIL("获取WOW64状态失败!");
            return;
        }
    
        if (bIsWow64){
            StringCchPrintf(szFullTitle, _countof(szFullTitle), TEXT("32位程序'%s'运行在64位OS上"), szTitle);
        } else{
            StringCchPrintf(szFullTitle, _countof(szFullTitle), TEXT("32位程序'%s'运行在32位OS上"), szTitle);
        }
    #endif
        SetWindowText(hwnd, szFullTitle);
    }
    
    
    //////////////////////////////////////////////////////////////////////////
    //显示CPU信息
    void ShowCPUInfo(HWND hwnd, WORD wProcessorArchitecture, WORD wProcessorLevel,
                     WORD wProcessorRevision){
        TCHAR szCPUArch[64] = TEXT("(未知)");
        TCHAR szCPULevel[64] = TEXT("(未知)");
        TCHAR szCPURev[64] = TEXT("(未知)");
    
        switch (wProcessorArchitecture)
        {
            //注意:AMD处理器被视为PROCESSOR_ARCHITECTUR_INTEL,在注册表的
            //HKLMHARDWAREDESCRIPTIONSystemCentralProcessor下的"VendorIdentifier"(代应商ID)
            //键的值为 "GenuineIntel" 或"AuthenticAMD"
        
        case PROCESSOR_ARCHITECTURE_INTEL:
            {
                _tcscpy_s(szCPUArch, _countof(szCPUArch), TEXT("Intel"));
                switch (wProcessorLevel)
                {
                case 3:
                case 4: //80386或80486
                    StringCchPrintf(szCPULevel, _countof(szCPULevel), TEXT("80%c86"), wProcessorLevel + '0');
                    StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("%c%d"), 
                                    HIBYTE(wProcessorRevision)+TEXT('A'),
                                    LOBYTE(wProcessorRevision));
                    break;
                    
                case 5:
                    _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("奔腾"));
                    StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %d,Stepping d"), 
                                    HIBYTE(wProcessorRevision),
                                    LOBYTE(wProcessorRevision));
                    break;
    
                case 6:
                    switch (HIBYTE(wProcessorRevision)) //Model
                    {
                    case 1:
                        _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("奔腾 Pro"));
                        break;
                    case 3:
                    case 5:
                        _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("奔腾 II"));
                        break;
    
                    case 6:
                        _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("赛扬"));
                        break;
                    case 7:
                    case 8:
                    case 11:
                        _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("奔腾 III"));
                        break;
    
                    case 9:
                    case 13:
                        _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("奔腾 M"));
                        break;
    
                    case 10:
                        _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("奔腾 至强"));
                        break;
    
                    case 15:
                        _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("Core 2 Duo"));
                        break;
                    default:
                        _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("未知奔腾"));
                        break;
                    }
                    StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %d,Stepping %d"), 
                                    HIBYTE(wProcessorRevision),LOBYTE(wProcessorRevision));
                    break;
    
                case 15:
                    _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("奔腾 4"));
                    StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %d,Stepping %d"),
                                    HIBYTE(wProcessorRevision), LOBYTE(wProcessorRevision));
                    break;
                }
            }
            break;
    
        case PROCESSOR_ARCHITECTURE_IA64:
            _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("IA-64"));
            StringCchPrintf(szCPULevel, _countof(szCPULevel), TEXT("%d"), wProcessorLevel);
            StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %c,Pass %d"),
                            HIBYTE(wProcessorRevision)+TEXT('A'),
                            LOBYTE(wProcessorRevision));
            break;
    
        case PROCESSOR_ARCHITECTURE_AMD64:
            _tcscpy_s(szCPULevel, _countof(szCPULevel), TEXT("AMD64"));
            StringCchPrintf(szCPULevel, _countof(szCPULevel), TEXT("%d"), wProcessorLevel);
            StringCchPrintf(szCPURev, _countof(szCPURev), TEXT("Model %c,Pass %d"),
                            HIBYTE(wProcessorRevision) + TEXT('A'),
                            LOBYTE(wProcessorRevision));
            break;
        case PROCESSOR_ARCHITECTURE_UNKNOWN:
        default:
            _tcscpy_s(szCPUArch, _countof(szCPUArch), TEXT("未知"));
            break;
        }
    
        SetDlgItemText(hwnd, IDC_PROCARCH, szCPUArch);
        SetDlgItemText(hwnd, IDC_PROCLEVEL, szCPULevel);
        SetDlgItemText(hwnd, IDC_PROCREV, szCPURev);
    }
    
    //////////////////////////////////////////////////////////////////////////
    BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam){
    
        chSETDLGICONS(hwnd, IDI_SYSINFO);
    
        //获得系统信息
        SYSTEM_INFO  sinf;
        GetSystemInfo(&sinf);
    
        //显示CPU信息
        ShowCPUInfo(hwnd, sinf.wProcessorArchitecture, sinf.wProcessorLevel,
                    sinf.wProcessorRevision);
    
        //显示页面大小
        TCHAR szBuf[50];
        SetDlgItemText(hwnd, IDC_PAGESIZE, BigNumToString(sinf.dwPageSize, szBuf, _countof(szBuf)));
    
        //显示进程可用的最小地址
        StringCchPrintf(szBuf, _countof(szBuf), TEXT("0x%p"), sinf.lpMinimumApplicationAddress);
        SetDlgItemText(hwnd, IDC_MINAPPADDR, szBuf);
    
        //显示进程可用的最大地址
        StringCchPrintf(szBuf, _countof(szBuf), TEXT("0x%p"), sinf.lpMaximumApplicationAddress);
        SetDlgItemText(hwnd, IDC_MAXAPPADDR, szBuf);
    
        //显示CPU掩码位
        StringCchPrintf(szBuf, _countof(szBuf), TEXT("0x%016I64X"),(__int64) sinf.dwActiveProcessorMask);
        SetDlgItemText(hwnd, IDC_ACTIVEPROCMASK, szBuf);
    
        //显示CPU核数
        SetDlgItemText(hwnd, IDC_NUMOFPROCS, BigNumToString(sinf.dwNumberOfProcessors, szBuf, _countof(szBuf)));
        
        //分配粒度
        SetDlgItemText(hwnd, IDC_ALLOCGRAN, BigNumToString(sinf.dwAllocationGranularity, szBuf, _countof(szBuf)));
        
        //显示对话框标题
        ShowBitness(hwnd);
        return TRUE;
    }
    
    //////////////////////////////////////////////////////////////////////////
    void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtrl, UINT codeNotity){
        switch (id)
        {
        case IDCANCEL:
            EndDialog(hwnd, id);
            break;
        }
    }
    
    
    //////////////////////////////////////////////////////////////////////////
    INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
        switch (uMsg)
        {
            chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
            chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
        }
        return FALSE;
    }
    
    //////////////////////////////////////////////////////////////////////////
    int WINAPI _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nShowCmd)
    {
        DialogBox(hInstance, MAKEINTRESOURCE(IDD_SYSINFO), NULL, Dlg_Proc);
        return 0;
    }

    //resource.h

    //{{NO_DEPENDENCIES}}
    // Microsoft Visual C++ 生成的包含文件。
    // 供 14_SysInfo.rc 使用
    //
    #define IDD_SYSINFO                     1
    #define IDC_PROCARCH                    100
    #define IDC_PAGESIZE                    101
    #define IDC_MINAPPADDR                  102
    #define IDC_MAXAPPADDR                  103
    #define IDC_ACTIVEPROCMASK              104
    #define IDC_NUMOFPROCS                  105
    #define IDC_PROCTYPE                    106
    #define IDC_ALLOCGRAN                   107
    #define IDC_PROCLEVEL                   108
    #define IDC_PROCREV                     109
    #define IDI_SYSINFO                     110
    // Next default values for new objects
    // 
    #ifdef APSTUDIO_INVOKED
    #ifndef APSTUDIO_READONLY_SYMBOLS
    #define _APS_NEXT_RESOURCE_VALUE        103
    #define _APS_NEXT_COMMAND_VALUE         40001
    #define _APS_NEXT_CONTROL_VALUE         1001
    #define _APS_NEXT_SYMED_VALUE           101
    #endif
    #endif

    //SysInfo.rc

    // Microsoft Visual C++ generated resource script.
    //
    #include "resource.h"
    
    #define APSTUDIO_READONLY_SYMBOLS
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 2 resource.
    //
    #include "winres.h"
    
    /////////////////////////////////////////////////////////////////////////////
    #undef APSTUDIO_READONLY_SYMBOLS
    
    /////////////////////////////////////////////////////////////////////////////
    // 中文(简体,中国) resources
    
    #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
    LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
    
    #ifdef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // TEXTINCLUDE
    //
    
    1 TEXTINCLUDE 
    BEGIN
        "resource.h"
    END
    
    2 TEXTINCLUDE 
    BEGIN
        "#include ""winres.h""
    "
        ""
    END
    
    3 TEXTINCLUDE 
    BEGIN
        "
    "
        ""
    END
    
    #endif    // APSTUDIO_INVOKED
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // Dialog
    //
    
    IDD_SYSINFO DIALOGEX 0, 0, 173, 108
    STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
    CAPTION "系统信息"
    FONT 10, "宋体", 400, 0, 0x86
    BEGIN
        RTEXT           "处理器架构:",IDC_STATIC,10,8,68,8,SS_NOPREFIX
        RTEXT           "ID_PROCARCH",IDC_PROCARCH,81,8,80,8,SS_NOPREFIX
        RTEXT           "处理器级别:",IDC_STATIC,10,18,68,8,SS_NOPREFIX
        RTEXT           "ID_PROCLEVEL",IDC_PROCLEVEL,81,18,80,8,SS_NOPREFIX
        RTEXT           "处理器修订版本:",IDC_STATIC,10,28,68,8,SS_NOPREFIX
        RTEXT           "ID_PROCREV",IDC_PROCREV,81,28,80,8,SS_NOPREFIX
        RTEXT           "处理器的数量:",IDC_STATIC,10,38,68,8,SS_NOPREFIX
        RTEXT           "ID_NUMOFPROCS",IDC_NUMOFPROCS,81,38,80,8,SS_NOPREFIX
        RTEXT           "可用处理器掩码:",IDC_STATIC,10,48,68,8,SS_NOPREFIX
        RTEXT           "ID_ACTIVEPROCMASK",IDC_ACTIVEPROCMASK,81,48,80,8,SS_NOPREFIX
        RTEXT           "分配粒度(字节):",IDC_STATIC,10,58,68,8,SS_NOPREFIX
        RTEXT           "ID_ALLOCGRAN",IDC_ALLOCGRAN,81,58,80,8,SS_NOPREFIX
        RTEXT           "页面大小(字节):",IDC_STATIC,10,68,68,8,SS_NOPREFIX
        RTEXT           "ID_PAGESIZE",IDC_PAGESIZE,81,68,80,8,SS_NOPREFIX
        RTEXT           "进程可用最小地址:",IDC_STATIC,10,78,68,8,SS_NOPREFIX
        RTEXT           "ID_MINAPPADDR",IDC_MINAPPADDR,81,78,80,8,SS_NOPREFIX
        RTEXT           "进程可用最大地址:",IDC_STATIC,10,88,68,8,SS_NOPREFIX
        RTEXT           "ID_MAXAPPADDR",IDC_MAXAPPADDR,81,88,80,8,SS_NOPREFIX
    END
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // DESIGNINFO
    //
    
    #ifdef APSTUDIO_INVOKED
    GUIDELINES DESIGNINFO
    BEGIN
        IDD_SYSINFO, DIALOG
        BEGIN
            LEFTMARGIN, 7
            RIGHTMARGIN, 166
            TOPMARGIN, 7
            BOTTOMMARGIN, 101
        END
    END
    #endif    // APSTUDIO_INVOKED
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // Icon
    //
    
    // Icon with lowest ID value placed first to ensure application icon
    // remains consistent on all systems.
    IDI_SYSINFO             ICON                    "SysInfo.ico"
    #endif    // 中文(简体,中国) resources
    /////////////////////////////////////////////////////////////////////////////
    
    
    
    #ifndef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 3 resource.
    //
    
    
    /////////////////////////////////////////////////////////////////////////////
    #endif    // not APSTUDIO_INVOKED

    14.2 虚拟内存状态——GlobalMemoryStatus函数

    (1)GlobalMemoryStatus函数(16位遗留的历史问题,可理解为VirtualMemoryStatus)

      ①VOID GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer);

      ②MEMORYSTATUS结构体

    字段

    描述

    DWORD dwLength

    结构体大小,等于sizeof(MEMORYSTATUS)。调用函数之前,必须初始化该成员

    DWORD dwMemoryLoad

    己用内存的百分比,介于0-100之间。

    SIZE_T dwTotalPhys

    物理内存总量(以字节为单位)

    SIZE_T dwAvailPhys

    可用物理内存(以字节为单位)

    SIZE_T dwTotalPageFile

    页交换文件总的大小

    SIZE_T dwAvailPageFile

    页交换文件中空闲部分的大小

    SIZE_T dwTotalVirtual

    用户可用的地址空间,即进程私有的那部分地址空间。

    SIZE_T dwAvailVitual

    当前空闲的地址空间。(注意这个成员是唯一与该进程有关的成员,所有其他成员适用于整个系统)。函数会将调用进程的地址空间中所有空闲的区域加起来

      ③该函数不支持物理内存或页交换文件大于4GB的情况。

    (2)GlobalMemoryStatusEx函数——支持内存大于4GB

      ①BOOL GlobalMemoryStatusEx(LPMEMORYSTATUSEX pmst);

      ②MEMORYSTATUSEX 结构体—与MEMORYSTATUSEX结构体中各字段的含义相同,但所有表示大小的字段都由SIZE_T改为DWORDLONG型,即64位,可以容纳大于4GB的值

    (3)获得进程的工作集

      ①工作集(WorkingSet):用来表示当前进程正在使用的物理存储器的数量。我们把一个进程的地址空间中被保存在内存里的那些页面称为它的工作集。

      ②GetProcessMemoryInfo(HANDLE hProcess,PROCESS_MEMORY_COUNTERS ppmc,DWORD cbSize);//定义在psapi.h头文件中(注意cbSize等于sizeof(PROCESS_MEMORY_COUNTERS))。

      ③PROCESS_MEMORY_COUNTERS_EX结构体

    字段

    描述

    DWORD cb

    结构体的大小

    DWORD PageFaultCount

    缺页中断次数

    SIZE_T PeakWorkingSetSize

    使用内存高峰值,自进程开始运行以来,曾经使用过的内存数量的最大值(字节)

    SIZE_T WorkingSetSize

    当前使用的内存。函数被调用时,进程正在使用的字节数(字节)

    SIZE_T QuotaPeakPagedPoolUsage

    使用页面缓存池高峰(字节)

    SIZE_T QuotaPagedPoolUsage

    当前使用页面缓存池(字节)

    SIZE_T QuotaPeakNonPagedPoolUsage

    使用非分页缓存池高峰(字节)

    SIZE_T QuotoNonPagedPoolUsage

    当前使用非分页缓存池(字节)

    SIZE_T PagefileUsage

    当前使用分页文件(字节)

    SIZE_T PeakPagefileUsage

    使用分页文件的高峰(字节)

    SIZE_T PrivateUsage

    应用程序调用new、malloc或VirtualAlloc函数来显式地分配了多少内存。

    14.3 NUMA机器中的内存管理

     

    多核环境中的NUMA架构示意图

    (1)非统一内存访问:(Non-Uniform Memory Access,NUMA)机器中的CPU即能访问自己节点的内存,也能访问其他节点的内存,虽然访问自己节点内存的速度要比访问外节点的内存要快得多。默认当线程提交物理存储器时,操作系统会尽量用CPU自己节点的内存来支持物理存储器。但如果没有足够的内存,也会使用外节点内存来支持物理存储器。

    (2)调用GlobalMemoryStatusEx函数时,ullAvailPhys参数返回的值是所有节点的可用内存的总量。

    (3)获取某个特定NUMA节点的内存数量的方法:

      ①调用GetNumaAvailableMemoryNode(UCHAR uNode,PULONGLONG pulAvailableBytes);参数uNode用来标识节点,参数pulAvailableBytes返回该节点的内存数量。

      ②获取CPU驻留在哪个NUMA节点:GetNumaProcessorNode(UCHAR Processor,PUCHAR NodeNumber);

      ③获取系统中节点总数:GetNumaHighestNodeNumber(PULONG pulHighestNodeNumber);

      ④获取某个节点的CPU列表:GetNumaNodeProcessorMask(UCHAR uNode,PULONGLONG pulProcessorMask);参数uNode是节点的数字标识,参数pulProcessorMask所指向的ULONGLONG变量用来返回位掩码,如果某一位被设置,表示该位对位的CPU就属于该节点。

     【VMStat程序】显示当前内存状态信息

    /*************************************************************************
    Module: VMStat.cpp
    Notices:Copyright(c) 2008 Jeffrey Richter & Christophe Nasarre
    *************************************************************************/
    
    #include "../../CommonFiles/CmnHdr.h"
    #include "resource.h"
    #include <Psapi.h> //供GetProcessMemoryInfo函数使用
    #include <tchar.h>
    #include <strsafe.h>
    
    
    //////////////////////////////////////////////////////////////////////////
    #pragma  comment(lib,"psapi.lib") //静态链接psapi.dll文件
    //////////////////////////////////////////////////////////////////////////
    //计时器ID
    #define IDT_UPDATE 1
    
    //////////////////////////////////////////////////////////////////////////
    BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam){
        chSETDLGICONS(hwnd, IDI_VMSTAT);
    
        //设置计时器,以便周期性地更新内存状态信息
        SetTimer(hwnd, IDT_UPDATE, 1 * 1000, NULL);
    
        //强制计时器发送更新消息
        FORWARD_WM_TIMER(hwnd, IDT_UPDATE, SendMessage); //立即更新一下
    
        return TRUE;
    }
    
    //////////////////////////////////////////////////////////////////////////
    void Dlg_OnTimer(HWND hwnd, UINT id){
        //初始化结构体
        MEMORYSTATUSEX ms = { sizeof(ms) };
        GlobalMemoryStatusEx(&ms);
    
        TCHAR szData[512] = { 0 };
        StringCchPrintf(szData, _countof(szData),
            TEXT("%d
    %I64d
    %I64d
    %I64d
    %I64d
    %I64d
    %I64d
    "),
            ms.dwMemoryLoad,
            ms.ullTotalPhys,
            ms.ullAvailPhys,
            ms.ullTotalPageFile,
            ms.ullAvailPageFile,
            ms.ullTotalVirtual,
            ms.ullAvailVirtual);
    
        SetDlgItemText(hwnd, IDC_DATA, szData);
    
        //获取当前进程工作集和私有地址空间
        PROCESS_MEMORY_COUNTERS_EX pmc = { sizeof(pmc) };
        GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS)&pmc, sizeof(pmc));
        StringCchPrintf(szData, _countof(szData), 
                        TEXT("%I64d KB
    %I64d KB"),
                        (__int64)pmc.WorkingSetSize /1024,
                        (__int64)pmc.PrivateUsage /1024);
        SetDlgItemText(hwnd, IDC_PROCESSDATA, szData);
    }
    
    //////////////////////////////////////////////////////////////////////////
    void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtrl, UINT codeNotify){
        switch (id)
        {
        case IDCANCEL:
            KillTimer(hwnd, IDT_UPDATE);
            EndDialog(hwnd, id);
            break;
        }
    }
    
    //////////////////////////////////////////////////////////////////////////
    INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
            chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
            chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
            chHANDLE_DLGMSG(hwnd, WM_TIMER, Dlg_OnTimer);
        }
        return FALSE;
    }
    
    //////////////////////////////////////////////////////////////////////////
    int WINAPI _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nShowCmd)
    {
        DialogBox(hInstance, MAKEINTRESOURCE(IDD_VMSTAT), NULL, Dlg_Proc);
        return 0;
    }

    //resource.h

    //{{NO_DEPENDENCIES}}
    // Microsoft Visual C++ 生成的包含文件。
    // 供 14_VMStat.rc 使用
    //
    #define IDD_VMSTAT                      1
    #define IDI_VMSTAT                      101
    #define IDI_ICON1                       102
    #define IDC_DATA                        1000
    #define IDC_WORKINGSET                  1001
    #define IDC_PROCESSDATA                 1001
    
    // Next default values for new objects
    // 
    #ifdef APSTUDIO_INVOKED
    #ifndef APSTUDIO_READONLY_SYMBOLS
    #define _APS_NEXT_RESOURCE_VALUE        103
    #define _APS_NEXT_COMMAND_VALUE         40001
    #define _APS_NEXT_CONTROL_VALUE         1001
    #define _APS_NEXT_SYMED_VALUE           101
    #endif
    #endif

    //VMStat.rc

    // Microsoft Visual C++ generated resource script.
    //
    #include "resource.h"
    
    #define APSTUDIO_READONLY_SYMBOLS
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 2 resource.
    //
    #include "winres.h"
    
    /////////////////////////////////////////////////////////////////////////////
    #undef APSTUDIO_READONLY_SYMBOLS
    
    /////////////////////////////////////////////////////////////////////////////
    // 中文(简体,中国) resources
    
    #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
    LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
    
    #ifdef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // TEXTINCLUDE
    //
    
    1 TEXTINCLUDE 
    BEGIN
        "resource.h"
    END
    
    2 TEXTINCLUDE 
    BEGIN
        "#include ""winres.h""
    "
        ""
    END
    
    3 TEXTINCLUDE 
    BEGIN
        "
    "
        ""
    END
    
    #endif    // APSTUDIO_INVOKED
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // Dialog
    //
    
    IDD_VMSTAT DIALOGEX 0, 0, 174, 102
    STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
    CAPTION "内存状态信息"
    FONT 10, "宋体", 400, 0, 0x86
    BEGIN
        LTEXT           "己用内存(%):
    物理内存总数(字节):
    可用物理内存(字节):
    交换文件总数(字节):
    交换文件空闲总数(字节):
    用户可用地址空间:
    当前空闲地址空间:",IDC_STATIC,9,8,91,56,0,WS_EX_RIGHT
        RTEXT           "Memory load:
    TotalPhys:
    AvailPhys:
    TotalPageFile:
    AvailPageFile:
    TotalVirtual:
    AvailVirtual:",IDC_DATA,102,8,61,56
        LTEXT           "当前进程工作集:
    私有地址空间:",IDC_STATIC,17,74,67,17,0,WS_EX_RIGHT
        LTEXT           "WorkingSet:
    PrivateBytes:",IDC_PROCESSDATA,86,74,61,17,0,WS_EX_RIGHT
        CONTROL         "",IDC_STATIC,"Static",SS_ETCHEDFRAME,9,70,158,1
    END
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // DESIGNINFO
    //
    
    #ifdef APSTUDIO_INVOKED
    GUIDELINES DESIGNINFO
    BEGIN
        IDD_VMSTAT, DIALOG
        BEGIN
            LEFTMARGIN, 7
            RIGHTMARGIN, 167
            TOPMARGIN, 7
            BOTTOMMARGIN, 95
        END
    END
    #endif    // APSTUDIO_INVOKED
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // Icon
    //
    
    // Icon with lowest ID value placed first to ensure application icon
    // remains consistent on all systems.
    IDI_VMSTAT              ICON                    "VMStat.ico"
    #endif    // 中文(简体,中国) resources
    /////////////////////////////////////////////////////////////////////////////
    
    
    
    #ifndef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 3 resource.
    //
    
    
    /////////////////////////////////////////////////////////////////////////////
    #endif    // not APSTUDIO_INVOKED
  • 相关阅读:
    mybatis自学历程(二)
    mybatis自学历程(一)
    Hibernate入门教程(二):Hibernate核心API
    Hibernate入门教程(一):入门示例(Myeclipse)
    Python中反射的简单应用
    Struts2的Action访问
    Myeclipse中dtd代码提示
    B/+、索引原理
    postgres 模糊匹配
    jvm_第三章:垃圾收集与内存分配策略
  • 原文地址:https://www.cnblogs.com/5iedu/p/4852712.html
Copyright © 2020-2023  润新知