虚拟内存使用
一、 简介
Windows提供了3中进行内存管理的方法,包括:
虚拟内存:一般用来管理大型数据结构,受到硬盘调页文件的支持
内存映射文件:常用来管理大型数据流和多进程共享。
内存堆:最适合用来管理大量的小对象。
二、 虚拟内存的使用
1、我们可以在进程的地址空间中保留一个区域:
PVOID VirtualAlloc(
PVOID pvAddress, 需要保留的地址
SIZE_T dwSize, 需要保留的地址大小
DWORD fdwAlloccationType, 是保留还是提交
DWORD fdwProtect); 保留页面的访问属性
第一个参数用于设定让系统地址将地址空间保留在什么地方,一般情况下,可将该参数设置位NULL,此时,系统将自动寻找适合的地址空间并保留之。
2、提交区域
提交内存区域也是通过VirtualAlloc函数来实现的,只是在fdwAlloccationType参数中传递MEM_COMMIT参数。
注:在提交保留的内存时,可以只提交被保留内存的一部分。
3、 同时保留并提交内存
同时保留并提交内存同样通过VirtualAlloc函数来实现的,只是在fdwAlloccationType参数中传递MEM_RESERVE | MEM_COMMIT参数。
4、 回收虚拟内存
回收映射到一个区域的物理存储区,或者是否这个地址空间区域,可通过调用VirtualFree函数。
BOOL VirtualFree(
LPVOID pvAddress, 需要释放的地址
SIZE_TO dwSize, 需要释放的空间大小,必须设置为0
DWORD fdwFreeType); 必须传递MEM_RELEASE
5、 取消提交虚拟内存
当想要从一个区域回收某些物理存储器,但却不释放该区域时,可调用VirtuallFree函数来取消虚拟内存的提交
此时必须设置需要释放的空间大小,并传递MEM_DECOMMIT给fdwFreeType参数。
6、 改变保护属性
我们可以通过VirtualProtect函数来改变已经提交的物理存储器的一个或多个页面的保护属性。
BOOL VirtualProtect(
PVOID pvAddress, 需要修改保护属性的地址
SIZE_T dwSize, 需要修改保护属性的大小
DWORD flNewProtect, 新的保护属性
PDWORD pflOldProtect); 旧的保护属性
三、 测试程序
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
void VirtualMemoryStatus(PVOID ptr);
void main()
{
/*保留虚拟内存*/
PVOID ptr = VirtualAlloc(NULL, 5*1024, MEM_RESERVE, PAGE_READWRITE);
VirtualMemoryStatus(ptr);
/*提交虚拟内存*/
VirtualAlloc(ptr, 4*1024, MEM_COMMIT, PAGE_READONLY);
VirtualMemoryStatus(ptr);
/*修改已提交内存的保护属性*/
PDWORD oldProtect = new DWORD();
VirtualProtect(ptr, 4 * 1024, PAGE_READWRITE, oldProtect);
VirtualMemoryStatus(ptr);
/*使用已提交内存*/
string str = "this is test the commit virtual memort !";
char *chPtr = (char *)ptr;
strcpy(chPtr, str.c_str());
cout << chPtr << endl;
/*查看部分部分提交后剩余部分的状态*/
PVOID pptr = (PBYTE)ptr + 4 * 1024;
VirtualMemoryStatus(pptr);
/*取消提交*/
VirtualFree(ptr, 4 * 1024, MEM_DECOMMIT);
VirtualMemoryStatus(ptr);
/*释放保留虚拟内存空间*/
VirtualFree(ptr, 0, MEM_RELEASE);
VirtualMemoryStatus(ptr);
system("pause");
}
/*查看给定虚拟地址状态函数*/
void VirtualMemoryStatus(PVOID ptr)
{
PMEMORY_BASIC_INFORMATION memoryBasicInfo = new MEMORY_BASIC_INFORMATION();
VirtualQuery(ptr, memoryBasicInfo, sizeof(MEMORY_BASIC_INFORMATION));
cout << memoryBasicInfo->BaseAddress << "/t" << memoryBasicInfo->AllocationBase << "/t"
<< memoryBasicInfo->RegionSize << "/t" ;
switch(memoryBasicInfo->State)
{
case MEM_FREE:
{
cout << "free";
break;
}
case MEM_RESERVE:
{
cout << "reserve";
break;
}
case MEM_COMMIT:
{
cout << "commit";
break;
}
}
cout << "/t";
switch(memoryBasicInfo->AllocationProtect)
{
case PAGE_NOACCESS:
{
cout << "N";
break;
}
case PAGE_READONLY:
{
cout << "R";
break;
}
case PAGE_READWRITE:
{
cout << "RW";
break;
}
case PAGE_EXECUTE:
{
cout << "E";
break;
}
case PAGE_EXECUTE_READ:
{
cout << "ER";
break;
}
case PAGE_EXECUTE_READWRITE:
{
cout << "ERW";
break;
}
}
cout << "/t";
switch(memoryBasicInfo->Protect)
{
case PAGE_NOACCESS:
{
cout << "N";
break;
}
case PAGE_READONLY:
{
cout << "R";
break;
}
case PAGE_READWRITE:
{
cout << "RW";
break;
}
case PAGE_EXECUTE:
{
cout << "E";
break;
}
case PAGE_EXECUTE_READ:
{
cout << "ER";
break;
}
case PAGE_EXECUTE_READWRITE:
{
cout << "ERW";
}
}
cout << "/t";
switch(memoryBasicInfo->Type)
{
case MEM_IMAGE:
{
cout << "image";
break;
}
case MEM_MAPPED:
{
cout << "mapped";
break;
}
case MEM_PRIVATE:
{
cout << "private";
break;
}
}
cout << endl;
}
运行结果:
003A 0000 003A 0000 8192 reserve RW private
003A 0000 003A 0000 4096 commit RW R private
003A 0000 003A 0000 4096 commit RW RW private
this is test the commit virtual memort !
003A 1000 003A 0000 4096 reserve RW private
003A 0000 003A 0000 8192 reserve RW private
003A 0000 00000000 393216 free N