第14章 虚拟内存

本文介绍了Windows系统中的内存管理机制,包括如何使用GetSystemInfo函数获取主机相关信息、利用GlobalMemoryStatus函数查询当前内存状态,并通过VirtualQuery及VirtualQueryEx函数来了解地址空间的状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

G e t S y s t e m I n f o函数将用于检索与主机相关的值:

VOID GetSystemInfo(LPSYSTEM_INFO psinf);

必须传递S Y S T E M _ I N F O结构的地址给这个函数。这个函数将初始化所有的结构成员然后返回。下面是S Y S T E M _ I N F O数据结构的样子。

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;
 
14.2 虚拟内存的状态

Wi n d o w s函数G l o b a l M e m o r y S t a t u s可用于检索关于当前内存状态的动态信息:

VOID GlobalMemoryStatus(LPMEMORYSTATUS pmst);

当调用G l o b a l M e m o r y S t a t u s时,必须传递一个M E M O RY S TAT U S结构的地址。下面显示了M O M O RY S TAT U S的数据结构。

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;

d w M e m o r y L o a d成员(图1 4 - 5中显示为Memory Load)给出了内存管理系统的大致繁忙程度。该数字的范围是0至1 0 0。计算这个值时使用的具体算法在Windows 98与Windows 2000上是不同的。根据将来的操作系统版本的情况,该算法还会有所变化。实际上,该成员变量报告的值是没有什么用处的。

d w To t a l P h y s成员(图1 4 - 5中显示为To t a l P h y s)用于指明存在的物理存储器( E A M)的总字节数。在128 MB 的Pentium II计算机上,这个值是133 677 056,它只比128 MB少540 672 个字节。G l o b a l M e m o r y S t a t u s之所以不报告全部的1 2 8 M B,原因是在引导进程中,系统将一些内存保留为非页面内存池。这些内存甚至不能被内核使用。d w Av a i l P h y s成员(图1 4 -5中显示为Av a i l P y h s)用于指明可供分配的物理存储器的总字节数。

d w To t a l P a g e F i l e成员(图1 4 - 5中显示为To t a l P a g e F i l e)用于指明你的硬盘上的页文件中包含的最大字节数。虽然V M S t a t报告的页文件当前是318 574 592字节,但是系统可以根据需要对页交换文件进行扩大和压缩。d w Av a i l P a g e F i l e成员(图1 4 - 5中显示为Av a i l P a g e F i l e)用于指明页文件中有233 046 016字节尚未提交给任何进程,因此,如果一个进程决定提交任何私有内存的话,目前就可以使用这些字节。

d w To t a l Vi r t u a l成员(图1 4 - 5中显示为To t a l Vi t u a l)用于指明每个进程的地址空间中私有的总字节数。它的值是2 147 352 576,比准确的2 GB少128 KB。从0 x 0 0 0 0 0 0 0 0至0 x 0 0 0 0 F F F F以及从0 x 7 F F F 0 0 0 0至0 x 7 F F F F F F F的两个分区是不能访问的地址空间,这正好等于128 KB这个差额。如果在Windows 98下运行V M S t a t,你将看到d w To t a l Vi r t u a l返回的值是2 143 289 344,这比准确的2 GB只少4 MB。之所以差4 MB,原因是系统决不允许应用程序访问从0 x 0 0 0 0 0 0 0 0至0 x 0 0 3 F F F F F之间的这个4 MB分区。

最后一个成员d w Av a i l Vi r t u a l(图1 4 - 5中显示为Av a i l Vi r t u a l)是该结构中专门用于调用G l o b a l M e m o r y S t a t u s的进程的唯一成员,所有其他成员在系统中的使用情况都是一样的,而不管是哪个进程调用G l o b a l M e m o r y S t a t u s。若要计算这个值, G l o b a l M e m o r y S t a t u s将调用进程的地址空间中的所有空闲区域相加。d w Av a i l Vi r t u a l的值2 136 846 336表示可供V M S t a t随意使用的空闲地址空间的数量。如果将d w To t a l Vi r t u a l的值减去d w Av a i l Vi r t u a l的值,你会看到V M S t a t在它的虚拟地址空间中保留了10 506 240个字节。

没有一个成员能够指明进程当前使用的物理存储器的数量。

 
// This function accepts a number and converts it to a
// string, inserting commas where appropriate.
PTSTR BigNumToString(LONG lNum, PTSTR szBuf) {

   TCHAR szNum[100];
   wsprintf(szNum, TEXT("%d"), lNum);
   NUMBERFMT nf;
   nf.NumDigits = 0;
   nf.LeadingZero = FALSE;
   nf.Grouping = 3;
   nf.lpDecimalSep = TEXT(".");
   nf.lpThousandSep = TEXT(",");
   nf.NegativeOrder = 0;
   GetNumberFormat(LOCALE_USER_DEFAULT, 0, szNum, &nf, szBuf, 100);
   return(szBuf);
}

 
14.3 确定地址空间的状态

 

Wi n d o w s提供了一个函数,可以用来查询地址空间中内存地址的某些信息(如大小,存储器类型和保护属性等)。

这个函数称为Vi r t u a l Q u e r y:

DWORD VirtualQuery(
   LPCVOID pvAddress,
   PMEMORY_BASIC_INFORMATION pmbi,
   DWORD dwLength);

Wi n d o w s还提供了另一个函数,它使一个进程能够查询另一个进程的内存信息:

DWORD VirtualQueryEx(
   HANDLE hProcess,
   LPCVOID pvAddress,
   PMEMORY_BASIC_INFORMATION pmbi,
   DWORD dwLength);
这两个函数基本相同,差别在于使用Vi r t u a l Q u e r y E x时,可以传递你想
要查询的地址空间信息的进程的句柄。调试程序和其他实用程序使用这个函数最多,几乎所
有的应用程序都只需要调用Vi r t u a l Q u e r y函数。当调用
Vi r t u a l Q u e r y(E x)函数时,p v A d d r e s s参数必须包含你想要
查询其信息的虚拟内存地址。P m b i参数是你必须分配的
M E M O RY _ B A S I C _ I N F O R M AT I O N结构的地址。该结构在
Wi n N T. 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;

最后一个参数是d w L e n g t h,用于设定M E M O RY _ B A S I C _ I N F O R M AT I O N结构的大小。Vi r t u a l Q u e r y(E x)函数返回拷贝到缓存中的字节的数量。

根据在p v A d d r e s s参数中传递的地址,Vi r t u a l Q u e r y(E x)函数将关于共享相同状态、保护属性和类型的相邻页面的范围信息填入M E M O RY _ B A S I C _ I N F O R M AT I O N结构中。表1 4 - 3描述了该结构的成员。

 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值