实验六 系统内存使用统计
一、实验目的
- 了解Windows内存管理机制,理解页式存储管理技术。
- 熟悉Windows内存管理基本数据结构。
- 掌握Windows内存管理基本API的使用。
二、实验准备
相关数据结构及API函数介绍
- 相关系统数据结构说明
系统结构MEMORYSTATUS中包含当前物理内存和虚拟内存和虚拟内存信息,使用函数GlobaiMemoryStatus()可以将这些信息存储在结构MEMORYSTATUS中。
结构原型:
Typedef struct_MRMORYSTATUS{
DWORD dwLength; //MOMORYSTATUS结构大小
DWORD dwMemoryLoad; //内存利用率
DWORD dwTotalPhys; //物理内存大小
DWORD dwAvailPhys; //空闲物理内存大小
DWORD dwTotalPageFile; //页文件大小
DWORD dwAvailPageFile; //空闲页文件大小
DWORD dwTotalVirtual; //虚拟地址空间大小
DWORD dwAvailVirtual; //空闲虚拟地址空间大小
} MEMORYSTATUS, *LPMEMORYSTAYUS;
成员说明:
- dwLength;MEMORYSTATUS数据结构的大小,单位为字节。
- dwMemoryLoad:当前内存利用率,取值范围为0~100%,0表示内存没有被使用,100%表示内存全部被使用。
- dwTotalPhys:物理内存的总字节数。
- dwAvailPhys:可用物理内存的字节数。
- dwTotalPageFile:页文件的总字节数。页文件是虚拟内存系统占用的磁盘空间。
- dwAvailPageFile:页文件中的可用字节数。
- dwTotalVirtual:用户模式下调用进程可以访问的虚拟地址空间总字节数。
- dwAvailVirtual:用户模式下调用进程虚拟地址空间中未提交和未保留的内存总字节数,即可用虚拟地址空间大小。
- 相关API函数介绍
获取系统物理内存和虚拟内存使用信息
原型:
VID GlobalMemoryStatus(
LPMEMORYSTATUS lpBuffer //指向MEMORYSTATUS数据结构
);
参数说明:
- lpBuffer: 指向MEMORYSTATUS数据结构的指针,函数GlobaiMemoryStatus()将内存的当前信息存储在该结构中。
返回值:
该参数没有返回值。
保留或提交某一点虚拟地址空间
函数VirtualAlloc()可以在调用进程的虚拟地址空间中保留或提交若干页面。保留意味着这段虚拟地址地址不能被使用,当提交时,这段虚拟地址才真正被分配给进程。
原型:
VPVOID VirtuaiAlloc(
LPVOID lpAddress, //待分配空间的起始位置
DWORD dwSize, //待分配空间的大小
DWORD flAllocationType, //分配类型
DWORD flaProtect //存取保护的类型
);
参数说明:
-
lpAddress:待分配空间的其实位置。若该值为NULL,系统将为其分配一合适的起始地址,否则用户要指定一个准确的起始地址。
-
dwSize:待分配空间的大小。如果参数lpAddress不为NULL,则待分配空间在lpAddress~ lpAddress+ dwSize范围内。
-
flAllocationType:分配类型,可以为表3-1所列标志的任意组合。
-
表3-1
标志 描述 MEM_COMMMIT 提交,即在内存或磁盘页文件中分配物理内存 MEM_RESERVE 保留进程的虚拟地址空间,而不分配物理内存。表留的空间在没有被释放之前,不能被其他分配操作如Malloe()和LocalAlloc()使用。被保留的地址空间可随后使用VirtuaiAlloc()函数提交 -
flProtect:指定存取保护的类型。若虚拟地址空间已经被提交,则在指定下面任何一个属性时要随同PAGE_GUARD(页保护)和PAGE_NOCACHE(页无缓存)这两个属性。存取保护位的类型如表3-2所示。
-
表3-2
志 描述 AGE_READONLY 被提交的虚拟地址空间只读 AGE_READWRITE 被提交的虚拟地址空间可读/写 AGE_EXECUTE 被提交的虚拟地址空间可执行 AGE_EXECUTE_READ 被提交的虚拟地址空间可执行、可读 AGE_EXECUTE_READWRITE 被提交的虚拟地址空间可执行、可读/写 AGE_GUARD 保护 AGE_NOACCESS 不允许访问 AGE_NOCACHE 无缓存
返回值:
如果函数调用成功,则返回值为已分配虚拟地址空间的起始地址。如果函数调用失败,则返回值为NULL。若要得到更多的错误信息,可调用GetLast6Error()函数。
释放或注销某一段虚拟地址空间
函数VirtualFree()用于释放或注销某一段虚拟地址空间。
原型:
BOOL VirtualFree(
LPVOID lpAddress, //待分配空间的起始位置
DWORD dwSize, //待分配空间的大小
DWORD dwFreeType //释放操作类型
);
参数说明:
-
lpAddress: 待释放空间的起始位置。如果dwFreeType值为MEM_RELEASE,该参数必须使用VirtualAlloc()函数返回的地址。
-
dwSize: 待释放空间的大小。如果dwFreeType值为MEM_RELEASE,该参数必须为0,否则待释放空间在lpAddress~ lpAddress+dwSize范围内。
-
dwFreeType: 释放类型。可以为表3-3所示标志的任意组合。
-
表3-3
志 描述 EM_DECOMMIT 注销提交,如果注销一个没有提交的虚拟地址空间,也不会导致失败,即提交或没有提交的虚拟地址空间都可以注销 EM_RELEASE 释放保留的虚拟地址空间,如果使用该标志,dwSize参数必须为0,否则函数失败
返回值:
如果函数调用成功,则返回值为非零。
如果函数调用失败,则返回值为零。若要得到更多的错误信息,可调用GetLastError()函数。
分配内存空间
原型:
void *malloc(site_t size);
参数说明:
- Size:要分配内存大小,单位为B(字节).
返回值:
该函数返回分配内存空间void类型的指针。如果返回NULL,说明没有有效的内存空间可供分配。
释放内存空间
原型:
Void free(void * memblock);
参数说明:
- *memblock:要释放的内存地址。
返回值:无。
用法举例:
/*MALLOC.C:This grogram allocates memory with
*malloc,then frees the memory with free
*/
#include<stdlib.h>
#include<stdio.h>
#include<malloc.h>
Void main(void)
{
Char * string;
/*Allocate space for a path name*/
String=malloc(_MAX_PATH); //分配内存空间
if(string==NULL)
printf(“Insufficient memory available\n”);
free(string);
printf(“Memory freed\n”);
}
}
三、实验内容
(一)实验内容
使用Windows系统提供的函数和数据结构显示系统存储空间的使用情况,当内存和虚拟存储空间变化时,观察系统显示变化情况。
(二)主要代码
// GetMemoryStatus.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "GetMemoryStatus.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
void GetMemSta(void);
/
// The one and only application object
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
LPVOID BaseAddr;
char * str;
GetMemSta();
printf("Now Allocate 32M Virtual Memory and 2M Physical Memory\n\n") ;
BaseAddr=VirtualAlloc(NULL,1024*1024*32, MEM_COMMIT,PAGE_READWRITE);
if (BaseAddr == NULL)
printf ("Virtual Allocate Fail\n");
str = (char * )malloc(1024*1024*2);
GetMemSta();
printf("Now Release 32M Virtual Memory and 2M Physical Memory\n\n");
if (VirtualFree(BaseAddr,0,MEM_RELEASE) == 0)
printf("Release Allocation Fail\n");
free (str);
GetMemSta();
return nRetCode;
}
void GetMemSta(void)
{
MEMORYSTATUS MemInfo ;
GlobalMemoryStatus (&MemInfo) ;
printf("\t Current Memory Status is : \n") ;
printf("\t Total Physical Memory is % dMB\n",MemInfo.dwTotalPhys/(1024*1024)) ;
printf("\t Available Physical Memoryis % dMB\n", MemInfo.dwAvailPhys/(1024*1024));
printf("\t Total Page File is % dMB\n",MemInfo.dwTotalPageFile/(1024*1024)) ;
printf("\t Available Page File is % dMB\n",MemInfo.dwAvailPageFile/(1024*1024)) ;
printf("\t Total Virtual Memory is % dMB\n",MemInfo.dwTotalVirtual/(1024*1024)) ;
printf("\t Available Virtual Memory is % dMB\n",MemInfo.dwAvailVirtual/(1024*1024)) ;
printf("\t Memory Load is % d% %\n\n",MemInfo.dwMemoryLoad) ;
}
四、实验结果和总结
- 程序开始运行时,显示可用物理内存为1736MB,可用页文件大小为3774MB,可用虚拟内存为2031MB。
- 当分别使用函数VirtualAlloc()和malloc()分配了32MB虚拟内存和2MB物理内存后,系统显示可用物理内存为1734MB,可用页文件大小为3740MB,可用虚拟内存为1997MB。
- 当分别使用函数VirtualFree()和free()释放了32MB虚拟内存和2MB物理内存后,系统的显示情况又恢复到了开始的情况。