在编程中对由于每个系统中页面大小,分配粒度等系统参数是不同的,因此在代码中不能将这些值写死,应该通过系统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;
}
如果需要获取当前系统中关系内存使用情况的信息可以使用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