第十四章:探索虚拟内存

1. 获取系统相关信息:

VOID GetSystemInfo( LPSTYSTEM_INFO psi);

其中SYSTEM_INFO结构体定义如下:

typedef struct _SYSTEM_INFO { 

union { 

DWORD  dwOemId; //

struct { 

WORD wProcessorArchitecture; //表示处理器的体系结构

WORD wReserved; //保留值.切勿使用

}; 

}; 

DWORD  dwPageSize; //页的大小

LPVOID lpMinimumApplicationAddress; //给出每个进程可用地址空间中最小的内存地址.由于 //每个进程地址空间中最开始的64K是闲置的.因此该值为0x00001000

LPVOID lpMaximumApplicationAddress; //进程的私有地址空间最大可用内存地址

DWORD_PTR dwActiveProcessorMask;//位掩码,用来表示哪些CPU处于活动状态

DWORD dwNumberOfProcessors; //表示机器中CPU的数量

DWORD dwProcessorType; //已经作废

DWORD dwAllocationGranularity; //表示用于预定地址空间分配的分配粒度.

WORD wProcessorLevel; //细分处理器的结构(如奔腾,..)

WORD wProcessorRevision; //进一步细分处理器(相对于wProcessorLevel).

} SYSTEM_INFO;

如果想要得到处理器详细信息,我们可调用GetLogicalProcessorInformation来获取.

Microsoft提供了一个成为Windows 32-bit On Windows64 bit的模拟层(简称WOW64),当32位应用程序通过WOW64运行时,GetSystemInfo返回值和64 bit可能不同.确定其运行环境可调用以下函数:

BOOL IsWow64Process(//替代函数IsOs(OS_WOW6432):TRUE表示32位在64位上运行

HANDLE hProcess, //进程句柄

PBOOL pbWow64Process) //返回值,TRUE表示是

函数返回值:FALSE表示把某些无效的值用作参数.如果32应用程序在32位windows上运行(或者64位在64位上运行)也是返回FLASE.只有32位应用程序在WOW64上运行屏蔽WowProcess才返回TRUE.此时可以利用GetNativeSystemInfo来取得原来的SYSTEM_INFO结构: void GetNativeSystemInfo(LPSYSTEM_INFO lpSystemInfo);

2. 虚拟内存状态:

VOID GlobalMemoryStatus( LPMEMORYSTSTUS lpBuffer)//使用前需初始化结构的大小

//即调用GlobalMemoryStatus

其中,MEMORYSTATUS结构如下:

ypedef struct _MEMORYSTATUS {

DWORD dwLength; //长度

DOWORD dwMemoryLoad;//大致告知系统有多忙

SIZE_T dwTotalPhys,//所有可用物理内存的总数

SIZE_T dwAvailPhys;//所有节点可用内存的总数

SIZE_T dwTotalPageFile;//表示硬盘上的也交换文件最多能存放多少子节点数据

SIZE_T  dwAvailVirtual;//表示页文件中有多少字节尚未使用

SIZE_T dwTotalVirtual;//表示地址空间中为各进程私有的那部分的字节数

SIZE_T dwAvailVirtual;//表示有多少闲置的虚拟空间可供使用

}MEMORYSTATUS,*LPMEMORYSTATUS;

另外如果确定应用程序会装有4GB内存的机器上运行,或者页交换文件的大小可能会大于4GB,那么就应该调用新的GlobalMemoryStatusEx( LPMEMORYSTATUS pmst);

ypedef struct _MEMORYSTATUSEX{

DWORD dwLength;

DWORD dwMemoryLoad;

DWORDLONG ullTotalPhys;

DWORDLONG ullAvailPhys;

DWORDLONG ullTotalPageFile;

DOWRDLONG ullAvaailPageFile;

DOWRDLONG ullTotalVirtual;

DWORDLONG ullAvailVirtual;

DWORDLONG ullAvailVirtual;

DWORDLONG ullAvailExtendVirtual;//表示当前进程的虚拟地址空间中尚未 //被预定的那一大块内存地址空间的大小.该成员只对特定配置中特定类 //型的CPU体系结构才有意义

}MEMORYSTATUSEX,*LPMEMORYSTATUSEX;

3. 非统一内存访问(NUMA):是指多个CPU情况下,CPU技能访问本地内存节点,也能访问非本地内存节点.如果想要知道某个特定的NUMA节点的内存数量可以调用如下函数:

BOOL GetNumaAvailableMemoryNode(

UCHAR uNode,//用来表示节点

PULONGLONG pulAvailableBytes);//返回节点的内存数量

CPU驻留哪个节点查询函数:

BOOL GetNumaProcessorNode(

UCHAR Processor,

PUCHAR NodeNumber);

获取节点数:

BOOL GetNumaHighestNodeNumber( 

PULONG pulHighestNodeNumber);

驻留在某个节点中的CPU列表:

BOOL GetNumaNodeProcessorMask(

UCHAR uNode, //节点的数字标示

[_out] PULONGLONG pulProcessorMask);//位掩码

获取进程当前工作集的大小和最大的工作集的大小:

BOOL GetProcessMemoryInfo( 

HANDLE hProcess.//具备PROCESS_QUERY_INFORMATION和PROCESS_VM_READ //访问权限的句柄

PPROCESS_MEMORY_COUNTERS ppmc,//

DWORD cbSize); //结构的大小

typedef struct _PROCESS_MEMORY_COUNTERS {

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;//通过调用new,mallocVirtualAlloc显示分配的内存数

} PROCESS_MEMORY_COUNTERS;

4. 虚拟内存映射表查询函数://查询本身进程

DWORD VirtualQuery(

LPCVOID pvAddress,//指向PMEMORY_BASIC_INFORMATION结构中填入相邻页面 //区间有关的信息

PMEMORY_BASIC_INFORMATION pmbi,

DWORD dwLength);

//查询非本身进程

DWORD VirtualQueryEx(

HANDLE hProcess,//待查询的进程句柄

LPCVOID pvAddress,

PMEMORY_BASIC_INFORMATION pmbi,

DWORD dwLength);//指向上一参数的结构大小

两个函数的返回值是实际使用字节数.

其中MEMORY_BASIC_INFORMATION结构定义如下:

tyopedef _MEMORY_BASIC_INFORMATION

{

PVOID BaseAddresss, //等于将参数pvAddress向下取整到页面的大小

PVOID AllocationBase; //标示出区域的基地址,该区域包含参数pvAddress所指定的地址

DWORD AllocationProtect; //标示出在最开始预订区域时为该区域指定的保护属性

SIZE_T RegionSize; //标示出区域的大小,以字节为单位.区域的起始地址为BaseAddress,

//区域中的所有页面拥有相同的保护属性,状态以及类型

DWORD State;//针对所有相邻的页面状态(MEM_FREE,MEM_RESERVEMEM_COMMIT). //果状态为MEM_FREE.

//那么AllocationBase,AllocationProtect,ProtectType成员都没有意义

DWORD Protect; //针对所有相邻的页面(前提是其保护属性,状态和类型与

//其中包含pvAddress参数中所指定地址的页面相同),标示出他们的保护属性(PAGE_*)

DWORD Type; //标示出区域中页面的类型(MEM_IMAGE,MEM_MAPPEDMEM_PRIVATE)

}MEMORY_BASIC_INFORMATION,PMEMORY_BASIC_INFORMATION;

为了得到更加详细的信息,可以使用作者封装的一个函数:

BOOL VMQuery(

HANDLE hProcess,

LPCVOID pvAddress,

PVMQUERY pVMQ);

PVMQ的定义:

typedef struct {

// Region information

PVOID  pvRgnBaseAddress;//区域起始地址

DWORD  dwRgnProtection;  // PAGE_*相当于AllocationBase字段

SIZE_T RgnSize; //相当于RegionSize字段

DWORD  dwRgnStorage;     // MEM_*: Free, Image, Mapped, Private相当于State

DWORD  dwRgnBlocks; //块的数量

DWORD  dwRgnGuardBlks;   // If > 0, region contains thread stack

BOOL   bRgnIsAStack;     // TRUE if region contains thread stack(通过猜测得到)

// Block information

PVOID  pvBlkBaseAddress;//块的起始地址

DWORD  dwBlkProtection;  // PAGE_* 块的保护属性

SIZE_T BlkSize; //块的大小,以字节为单位

DWORD  dwBlkStorage;// MEM_*: Free, Reserve, Image, Mapped, Private(表示块存储器的类型

} VMQUERY, *PVMQUERY;

注意:因为该函数运行起来需要调用多次VirtualQueryEx,这就意味着它的执行速度会很慢.

你可能感兴趣的:(工作,windows,image,basic,System,64bit)