Windows核心编程笔记(十四)探索虚拟内存

在编程中对由于每个系统中页面大小,分配粒度等系统参数是不同的,因此在代码中不能将这些值写死,应该通过系统API动态获取这些值。

GetSystemInfo可以获取一些基本的系统信息


void WINAPI GetSystemInfo(
  __out  LPSYSTEM_INFO lpSystemInfo
);

需要传入一个被写的SYSTEM_INFO结构体

typedef struct _SYSTEM_INFO {
  union {
    DWORD  dwOemId;
    struct {
      WORD wProcessorArchitecture;  处理器体系结构
      WORD wReserved;
    } ;
  } ;
  DWORD     dwPageSize;   //页面大小
  LPVOID    lpMinimumApplicationAddress;  //进程最小可用虚拟机地址
  LPVOID    lpMaximumApplicationAddress; //进程私有空间最大可用内存地址
  DWORD_PTR dwActiveProcessorMask;  //活动CPU掩码
  DWORD     dwNumberOfProcessors;  //CPU数量
  DWORD     dwProcessorType;
  DWORD     dwAllocationGranularity;  //分配粒度
  WORD      wProcessorLevel;
  WORD      wProcessorRevision;
} SYSTEM_INFO;


测试:

#define _WIN32_WINNT 0x0600
#include <iostream>
#include <windows.h>
#include <winbase.h>
#include <Shlwapi.h>
//#include <strsafe.h>
//#include <threadpoolapiset.h>
using namespace std;


int main(int argc,char *argv[])
{

    SYSTEM_INFO info;
    BOOL IsWow64;
    IsWow64Process(GetCurrentProcess(),&IsWow64);
    if(IsWow64)
    {
        GetNativeSystemInfo(&info);
    }
    else
    {
        GetSystemInfo(&info);
    }


    cout<<"PageSize: "<<info.dwPageSize<<" MiniAddr: "<<info.lpMinimumApplicationAddress<<endl;
    cout<<"MaxAddr: "<<info.lpMaximumApplicationAddress<<" AllocationGranularity: "<<info.dwAllocationGranularity<<endl;
    cout<<"Processors: "<<info.dwNumberOfProcessors<<" ActiveProcessor: "<<info.dwActiveProcessorMask<<endl;
    if(info.wProcessorArchitecture == 9)
    {
        cout<<"ProcessArchitecture: x64 (AMD or Intel)"<<endl;
    }
    else
    {
        cout<<"ProcessorArchitecture: X86"<<endl;
    }
    return 0;
}





如果需要获取CPU的信息 需要使用GetLogicalProcessorInformation, 可以获取CPU的物理数量,核心数量,逻辑数量,以及一二三级缓存的数量。


BOOL WINAPI GetLogicalProcessorInformation(
  __out    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer,
  __inout  PDWORD ReturnLength
);

MSDN给出了示例代码


#include <windows.h>
#include <malloc.h>
#include <stdio.h>
#include <tchar.h>
#define    _tprintf  wprintf
typedef BOOL (WINAPI *LPFN_GLPI)(
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,
    PDWORD);


// Helper function to count set bits in the processor mask.
DWORD CountSetBits(ULONG_PTR bitMask)
{
    DWORD LSHIFT = sizeof(ULONG_PTR)*8 - 1;
    DWORD bitSetCount = 0;
    ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;
    DWORD i;

    for (i = 0; i <= LSHIFT; ++i)
    {
        bitSetCount += ((bitMask & bitTest)?1:0);
        bitTest/=2;
    }

    return bitSetCount;
}

int _cdecl _tmain ()
{
    LPFN_GLPI glpi;
    BOOL done = FALSE;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
    DWORD returnLength = 0;
    DWORD logicalProcessorCount = 0;
    DWORD numaNodeCount = 0;
    DWORD processorCoreCount = 0;
    DWORD processorL1CacheCount = 0;
    DWORD processorL2CacheCount = 0;
    DWORD processorL3CacheCount = 0;
    DWORD processorPackageCount = 0;
    DWORD byteOffset = 0;
    PCACHE_DESCRIPTOR Cache;

    glpi = (LPFN_GLPI) GetProcAddress(
                            GetModuleHandle(TEXT("kernel32")),
                            "GetLogicalProcessorInformation");
    if (NULL == glpi)
    {
        _tprintf(TEXT("\nGetLogicalProcessorInformation is not supported.\n"));
        return (1);
    }

    while (!done)
    {
        DWORD rc = glpi(buffer, &returnLength);

        if (FALSE == rc)
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
            {
                if (buffer)
                    free(buffer);

                buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(
                        returnLength);

                if (NULL == buffer)
                {
                    _tprintf(TEXT("\nError: Allocation failure\n"));
                    return (2);
                }
            }
            else
            {
                _tprintf(TEXT("\nError %d\n"), GetLastError());
                return (3);
            }
        }
        else
        {
            done = TRUE;
        }
    }

    ptr = buffer;

    while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
    {
        switch (ptr->Relationship)
        {
        case RelationNumaNode:
            // Non-NUMA systems report a single record of this type.
            numaNodeCount++;
            break;

        case RelationProcessorCore:
            processorCoreCount++;

            // A hyperthreaded core supplies more than one logical processor.
            logicalProcessorCount += CountSetBits(ptr->ProcessorMask);
            break;

        case RelationCache:
            // Cache data is in ptr->Cache, one CACHE_DESCRIPTOR structure for each cache.
            Cache = &ptr->Cache;
            if (Cache->Level == 1)
            {
                processorL1CacheCount++;
            }
            else if (Cache->Level == 2)
            {
                processorL2CacheCount++;
            }
            else if (Cache->Level == 3)
            {
                processorL3CacheCount++;
            }
            break;

        case RelationProcessorPackage:
            // Logical processors share a physical package.
            processorPackageCount++;
            break;

        default:
            _tprintf(TEXT("\nError: Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value.\n"));
            break;
        }
        byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
        ptr++;
    }

    _tprintf(TEXT("\nGetLogicalProcessorInformation results:\n"));
    _tprintf(TEXT("Number of NUMA nodes: %d\n"),
             numaNodeCount);
    _tprintf(TEXT("Number of physical processor packages: %d\n"),
             processorPackageCount);
    _tprintf(TEXT("Number of processor cores: %d\n"),
             processorCoreCount);
    _tprintf(TEXT("Number of logical processors: %d\n"),
             logicalProcessorCount);
    _tprintf(TEXT("Number of processor L1/L2/L3 caches: %d/%d/%d\n"),
             processorL1CacheCount,
             processorL2CacheCount,
             processorL3CacheCount);

    free(buffer);

    return 0;
}



我的CPU是 I7-4720HQ   运行结果如下



如果需要获取当前系统中关系内存使用情况的信息可以使用GlobalMemoryStatusEx

BOOL WINAPI GlobalMemoryStatusEx(
  __inout  LPMEMORYSTATUSEX lpBuffer
);



typedef struct _MEMORYSTATUSEX {
  DWORD     dwLength;
  DWORD     dwMemoryLoad; //已使用内存数量
  DWORDLONG ullTotalPhys;  //系统物理内存总量
  DWORDLONG ullAvailPhys;  //空闲的物理内存
  DWORDLONG ullTotalPageFile;//页交换文件大小
  DWORDLONG ullAvailPageFile;//空闲的页交换空间
  DWORDLONG ullTotalVirtual;  //进程可使用虚拟机地址空间大小
  DWORDLONG ullAvailVirtual;  //空闲的虚拟地址空间大小
  DWORDLONG ullAvailExtendedVirtual;
} MEMORYSTATUSEX, *LPMEMORYSTATUSEX


如果需要获取当前进程的内存使用情况 可以使用GetProcessMemoryInfo

BOOL WINAPI GetProcessMemoryInfo(
  __in   HANDLE Process,
  __out  PPROCESS_MEMORY_COUNTERS ppsmemCounters,
  __in   DWORD cb
);

typedef struct _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 QuotaNonPagedPoolUsage;  //非分页池大小
  SIZE_T PagefileUsage; //页交换文件使用大小
  SIZE_T PeakPagefileUsage; //历史页交换文件使用
  SIZE_T PrivateUsage;  //进程运行过程中申请的内存大小
} PROCESS_MEMORY_COUNTERS_EX, *PPROCESS_MEMORY_COUNTERS_EX



测试:

#include <windows.h>
#include <stdio.h>
#include <Psapi.h>

#define DIV (1024*1024)


#define WIDTH 7

int main(int argc, char *argv[])
{
  MEMORYSTATUSEX statex;
  PROCESS_MEMORY_COUNTERS  counter;
  counter.cb = sizeof(counter);

  statex.dwLength = sizeof (statex);

  GlobalMemoryStatusEx (&statex);
  GetProcessMemoryInfo(GetCurrentProcess(),&counter,counter.cb);
  printf ("GlobalMemoryStatusEx : \r\n\r\n");
  printf ("There is  %*ld percent of memory in use.\n",
          WIDTH, statex.dwMemoryLoad);
  printf ("There are %*I64d total Mbytes of physical memory.\n",
          WIDTH, statex.ullTotalPhys/DIV);
  printf ("There are %*I64d free Mbytes of physical memory.\n",
          WIDTH, statex.ullAvailPhys/DIV);
  printf ("There are %*I64d total Mbytes of paging file.\n",
          WIDTH, statex.ullTotalPageFile/DIV);
  printf ("There are %*I64d free Mbytes of paging file.\n",
          WIDTH, statex.ullAvailPageFile/DIV);
  printf ("There are %*I64d total Mbytes of virtual memory.\n",
          WIDTH, statex.ullTotalVirtual/DIV);
  printf ("There are %*I64d free Mbytes of virtual memory.\n",
          WIDTH, statex.ullAvailVirtual/DIV);

  printf ("There are %*I64d free Mbytes of extended memory.\r\n\r\n",
          WIDTH, statex.ullAvailExtendedVirtual);



  /************************************************************************/
#define DIV 1024
  printf ("GetProcessMemoryInfo : \r\n\r\n");

  printf ("There are   %*I64d KBbyte of page fault \n",
          WIDTH, counter.PageFaultCount/DIV);
  printf ("There are %*I64d Kbytes of historic working memory\n",
          WIDTH, counter.PeakWorkingSetSize/DIV);
  printf ("There are %*I64d Kbytes of working memory.\n",
          WIDTH, counter.WorkingSetSize/DIV);
  printf ("There are %*I64d Kbytes of historic page pool.\n",
          WIDTH, counter.QuotaPeakPagedPoolUsage/DIV);
  printf ("There are %*I64d Kbytes of page pool.\n",
          WIDTH, counter.QuotaPagedPoolUsage/DIV);
  printf ("There are %*I64d Kbytes of historic no-pageed pool.\n",
          WIDTH, counter.QuotaPeakNonPagedPoolUsage/DIV);
  printf ("There are %*I64d Kbytes of no-pageed pool.\n",
          WIDTH, counter.QuotaNonPagedPoolUsage/DIV);

  printf ("There are %*I64d Kbytes of historic page file in using.\n",
          WIDTH, counter.PeakPagefileUsage);
  printf ("There are %*I64d Kbytes of page file in using.\n",
          WIDTH, counter.PagefileUsage);

  return 0;
}








如果要查询进程虚拟地址空间的某个地址所属的块信息 可以使用VirtualQueryEx

SIZE_T WINAPI VirtualQueryEx(
  __in      HANDLE hProcess,
  __in_opt  LPCVOID lpAddress,
  __out     PMEMORY_BASIC_INFORMATION lpBuffer,
  __in      SIZE_T dwLength
);


typedef struct _MEMORY_BASIC_INFORMATION {
  PVOID  BaseAddress;  //区域基地址
  PVOID  AllocationBase;//使用VirtualAlloc分配的基地址
  DWORD  AllocationProtect; //保护属性
  SIZE_T RegionSize;    //区域大小
  DWORD  State;     //页属性
  DWORD  Protect;  //区域属性
  DWORD  Type;  //区域类型
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;


详细参见 随书代码中的VMMap

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值