Windows编程--虚拟内存基础
系统信息
许多操作系统的值是根据主机而定的,比如页面的大小,分配粒度的大小等。这些值决不应该用硬编码的形式放入你的源代码。相反,你始终都应该在进程初始化的时候检索这些值,并在你的源代码中使用检索到的值。GetSystemInfo函数将用于检索与主机相关的值
VOID GetSystemInfo(LPSYSTEM_INFO psinf);
SYSTEM_INFO数据结构的样子。
typedef struct _SYSTEM_INFO
{
union
{
DWORD dwOemId; //Obsolete, do not use
struct
{
WORD wProcessorArchitecture;
WORD wReserved;
};
};
DWORD dwPageSize;
LPVOID lpMinimumApplicationAddress;
LPVOID lpMaximumApplicationAddress;
DWORD_PTR dwActiveProcessorMask;
DWORD dwNumberOfProcessors;
DWORD dwProcessorType;
DWORD dwAllocationGranularity;
WORD wProcessorLevel;
WORD wProcessorRevision;
} SYSTEM_INFO, *LPSYSTEM_INFO;
与内存有关的成员函数(其它变可参看MSDN)
dwPageSize 用于显示CPU的页面大小。在x86 CPU上,这个值是4096字节。在Alpha CPU 上,这个值是8192字节。在IA-64上,这个值是8192字节
lpMinimumApplicationAddress用于给出每个进程的可用地址空间的最小内存地址。在Windows 98上,这个值是4 194 304,或0x00400000,因为每个进程的地址空间中下面的4MB是不能使用的。在Windows 2000上,这个值是65 536或0x00010000,因为每个进程的地址空间中开头的64KB总是空闲的
lpMaximumApplicationAddress用于给出每个进程的可用地址空间的最大内存地址。在Windows 98 上,这个地址是2 147 483 647或0x7FFFFFFF,因为共享内存映射文件区域和共享操作系统代码包含在上面的2GB分区中。在Windows 2000上,这个地址是内核方式内存开始的地址,它不足64KB
dwAllocationGranularity 显示保留的地址空间区域的分配粒度。
虚拟内存的状态
Windows函数GlobalMemoryStatus可用于检索关于当前内存状态的动态信息:
VOID GlobalMemoryStatus(LPMEMORYSTATUS pmst);
当调用GlobalMemoryStatus时,必须传递一个MEMORYSTATUS结构的地址。下面显示了MOMORYSTATUS的数据结构。
typedef struct _MEMORYSTATUS
{
DWORD dwLength;
DWORD dwMemoryLoad;
SIZE_T dwTotalPhys;
SIZE_T dwAvailPhys;
SIZE_T dwTotalPageFile;
SIZE_T dwAvailPageFile;
SIZE_T dwTotalVirtual;
SIZE_T dwAvailVirtual;
} MEMORYSTATUS, *LPMEMORYSTATUS;
在调用GlobalMemoryStatus之前,必须将dwLength成员初始化为用字节表示的结构的大小,即一个MEMORYSTATUS结构的大小。
如果希望应用程序在内存大于4GB的计算机上运行,或者合计交换文件的大小大于4GB,那么可以使用新的GlobalMemoryStatusEx函数:
MEMORYSTATUSEX结构的地址:
BOOL GlobalMemoryStatusEx(LPMEMORYSTATUSEX pmst);
必须给该函数传递新的
typedef struct _MEMORYSTATUSEX
{
DWORD dwLength;
DWORD dwMemoryLoad;
DWORDLONG ullTotalPhys;
DWORDLONG ullAvailPhys;
DWORDLONG ullTotalPageFile;
DWORDLONG ullAvailPageFile;
DWORDLONG ullTotalVirtual;
DWORDLONG ullAvailVirtual;
DWORDLONG ullAvailExtendedVirtual;
} MEMORYSTATUSEX, *LPMEMORYSTATUSEX;
这个结构与原先的MEMORYSTATUS结构基本相同,差别在于新结构的所有成员的大小都是6 4位宽,因此它的值可以大于4GB。最后一个成员是ullAv ailExtendedVirtual,用于指明在调用进程的虚拟地址空间的极大内存(VLM)部分中未保留内存的大小。该VLM部分只适用于某些配置中的某些CPU结构。
确定地址空间的状态
Windows提供了一个函数,可以用来查询地址空间中内存地址的某些信息(如大小,存储器类型和保护属性等)。
这个函数称为VirtualQuery:
DWORD VirtualQuery(
LPCVOID pvAddress,
PMEMORY_BASIC_INFORMATION pmbi,
DWORD dwLength);
Windows还提供了另一个函数,它使一个进程能够查询另一个进程的内存信息:
DWORD VirtualQueryEx(
HANDLE hProcess,
LPCVOID pvAddress,
PMEMORY_BASIC_INFORMATION pmbi,
DWORD dwLength);
这两个函数基本相同,差别在于使用VirtualQueryEx时,可以传递你想要查询的地址空间信息的进程的句柄。调试程序和其他实用程序使用这个函数最多,几乎所有的应用程序都只需要调用VirtualQuery函数。
当调用VirtualQuery(Ex)函数时,
pvAddress参数必须包含你想要查询其信息的虚拟内存地址。
Pmbi参数是你必须分配的MEMORY_BASIC_INFORMATION结构的地址。该结构在WinNT.h文件中定义为下面的形式:
typedef struct _MEMORY_BASIC_INFORMATION
{
PVOID BaseAddress;
PVOID AllocationBase;
DWORD AllocationProtect;
SIZE_T RegionSize;
DWORD State;
DWORD Protect;
DWORD Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
最后一个参数是dwLength,用于设定MEMORY_BASIC_INFORMATION结构的大小。VirtualQuery(Ex)函数返回拷贝到缓存中的字节的数量。
FangSH 19:08 2011-1-6