分享

管理进程的虚拟内存

 贫穷的小悍马 2011-09-07

管理进程的虚拟内存:
进程的虚拟内存地址空间内存页面存在3种状态(大多数情况下,一页大小4KB):
空闲的(Free)            进程不能访问这种页面,因为页面没有被分配,
                                  任何属于这种页面的虚拟内存地址进行访问都会引起异常
保留的(Reserved)      页面被保留以被将来用,这些页面己经被分配,但是还没有使用,
                                  物理地址空间中的内存中不存在其对应的物理内存分页.处理保留
                                  状态的内存分页也不能被访问.
提交的(Committed)    内存已经被分配,并且已经被使用,具有与之对应的物理空间地址
                                  空间中的内存分页
                   
分配和释放可读可写的虚拟内存页面
使用VirtualAlloc和VirtualAllocEx分配虚拟内存时,可以指定分配的内存页面
是保留的还是提交的.直接分配完成后就可以对内存进行访问.

(1)VirtualAlloc
函数功能是"保留"或"提交"内存页面,将"空闲的"内存页面变为"保留的"或"已提交"
的,将"保留的"页面变为"提交的"
LPVOID VirtualAlloc(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
);
lpAddress:             输入参数,分配的起始位置.
dwSize:                   输入参数,所需要分配的内存区域大小.
flAllocationType:     输入参数,分配的类型,决定了是保留一段内存区域,还是提交,还是同时完成.
                               设置为MEM_COMMIT,将提交内存页面;MEM_RESERVE,保留页面;MEM_COMMIT|MEM_RESERVE
                               直接从空闲页面提交为"已提交的"页面.
flProtect:                  输入参数,内存的保护属性
返回值:
返回LPVOID类型的值,表示分配到内存的起始地址,如果返回NULL,表示失败,使用GetLastError函数获取错误信息.

(2)VirtualFree
将内存状态从"已提交的"变为"保留的",或将"保留的"变为"空闲的"或同时进行.VirtualAlloc的反向工作.
BOOL VirtualFree(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD dwFreeType
);
lpAddress:输入参数,需要改变状态的内存区域的起始地址.
dwSize:输入参数,需要改变状态的内存区域的大小,以字节为单位.
dwFreeType:
MEM_DECOMMIT             Decommits the specified region of committed pages.
                                         An attempt to decommit an uncommitted page does not cause the function to fail.
                                         This means that a range of committed or uncommitted pages can be decommitted
                                        without being concerned about a failure.

MEM_RELEASE              Releases the specified region of reserved pages.
                                       If this flag is specified, the dwSize parameter must be zero or the function fails.


(3)VirtualFreeEx
释放由VirtualAllocEx分配的内存,功能,使用方法和VirtualFree类似.
BOOL VirtualFreeEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD dwFreeType
);

code:
//virtual.c
//分配和释放可读可写的虚拟内存页面
/* 头文件 */
#include <windows.h>
#include <stdio.h>

/*************************************
* int main(void)
* 功能 演示虚拟内存的使用
*
* 参数 未使用
**************************************/
int main(void)
{
SIZE_T sizeVirtual = 4000;   //大小
LPVOID lpRound = (LPVOID)0x100000FF; //地址
MEMORY_BASIC_INFORMATION mbi; //内存信息

//分配内存,直接分配已提交的内存
LPVOID lpAddress = VirtualAlloc(
   lpRound,sizeVirtual,
   MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE
   );
if(lpAddress == NULL)
{
   printf("VirtualAlloc error: %d\n",GetLastError());
   return 1;
}
printf("Alloc:MEM_COMMIT|MEM_RESERVE\n");
//复制数据到内存中
CopyMemory(lpAddress,"hello",lstrlen("hello"));
printf("分配、复制成功,地址:0x%.8x,内容:%s\n",
   lpAddress,lpAddress);
//获取内存信息并打印
VirtualQuery(lpAddress,&mbi,sizeof(mbi));
printf("使用VirtualQuery获得的信息:\n"
   "BaseAddress:0x%.8x\tAllocationBase:0x%.8x\t"
   "AllocationProtect:0x%.8x\tRegionSize:%u\t"
   "State:0x%.8x\tProtect:0x%.8x\tType:0x%.8x\n",
   mbi.BaseAddress,mbi.AllocationBase,
   mbi.AllocationProtect,mbi.RegionSize,
   mbi.State,mbi.Protect,mbi.Type
   );

////设置为READ-ONLY属性
//if(!VirtualProtect(lpAddress,0,PAGE_READONLY,NULL))
//{
// printf("VirtualProtect error: %d",GetLastError());
// return 1;
//}
////测试READ-ONLY属性,异常
//CopyMemory(lpAddress,"read only",lstrlen("read only"));
//printf(lpAddress);
////获取内存信息并打印
//VirtualQuery(lpAddress,&mbi,sizeof(mbi));
//printf("使用VirtualQuery获得的信息:\n"
// "BaseAddress:0x%.8x\tAllocationBase:0x%.8x\t"
// "AllocationProtect:0x%.8x\tRegionSize:%d\t"
// "State:0x%.8x\tProtect:0x%.8x\tType:0x%.8x\n",
// mbi.BaseAddress,mbi.AllocationBase,
// mbi.AllocationProtect,mbi.RegionSize,
// mbi.State,mbi.Protect,mbi.Type
// );

//DECOMMIT释放,页面将变为保留状态
printf("Free: DECOMMIT\n");
if(!VirtualFree(lpRound,sizeVirtual,MEM_DECOMMIT))
{
   printf("VirtualFree error: %d",GetLastError());
   return 1;
}
//获取内存信息并打印
VirtualQuery(lpAddress,&mbi,sizeof(mbi));
printf("使用VirtualQuery获得的信息:\n"
   "BaseAddress:0x%.8x\tAllocationBase:0x%.8x\t"
   "AllocationProtect:0x%.8x\tRegionSize:%u\t"
   "State:0x%.8x\tProtect:0x%.8x\tType:0x%.8x\n",
   mbi.BaseAddress,mbi.AllocationBase,
   mbi.AllocationProtect,mbi.RegionSize,
   mbi.State,mbi.Protect,mbi.Type
   );
//释放内存
printf("Free:RELEASE\n");
if(!VirtualFree(lpAddress,0,MEM_RELEASE))
{
   printf("VirtualFree error: %d",GetLastError());
   return 1;
}
return 0;
}

修改内存页面状态和保护属性,将页面锁定在物理内存中
VirtualAlloc和VirtualFree函数改变内存状态,还可以用VirtualProtect改变页面属性.
BOOL VirtualProtect(
LPVOID lpAddress,
DWORD dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect
);
lpflOldProtect输出参数,指向保存原保护属性值的DWORD变量,可以为NULL.

VirtualLock
BOOL VirtualLock(
LPVOID lpAddress,
SIZE_T dwSize
);

BOOL VirtualUnlock(
LPVOID lpAddress,
SIZE_T dwSize
);

修改内存保护页面
////设置为READ-ONLY属性
//if(!VirtualProtect(lpAddress,0,PAGE_READONLY,NULL))
//{
// printf("VirtualProtect error: %d",GetLastError());
// return 1;
//}
////测试READ-ONLY属性,异常
//CopyMemory(lpAddress,"read only",lstrlen("read only"));
//printf(lpAddress);
////获取内存信息并打印
//VirtualQuery(lpAddress,&mbi,sizeof(mbi));
//printf("使用VirtualQuery获得的信息:\n"
// "BaseAddress:0x%.8x\tAllocationBase:0x%.8x\t"
// "AllocationProtect:0x%.8x\tRegionSize:%d\t"
// "State:0x%.8x\tProtect:0x%.8x\tType:0x%.8x\n",
// mbi.BaseAddress,mbi.AllocationBase,
// mbi.AllocationProtect,mbi.RegionSize,
// mbi.State,mbi.Protect,mbi.Type
// );


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多