撤销调拨物理存储器及释放区域。
要撤销调拨给区域的物理存储器或是释放地址空间中的一整块区域。可以调用VirtualFree函数:
BOOL VirtualFree( LPVOID pvAddress, SIZE_T dwSize, DWORD fdwFreeType); |
pvAddress参数必须是区域的基地址。该地址就是预定区域时VirtualAlloc返回的地址。由于系统在内部会记录该地址处的区域大小,因此我们可以且必须传入0给dwSize。
当传入MEM_RELEASE给fdwFreeType时是想告诉系统撤销调拨给该区域的所有物理存储器,并释放该区域。
我们可以撤销调拨给该区域的一部分物理存储器。此时需要传入pvAddress来告诉系统我们想要撤销调拨的区域的起始地址。dwSize传入想要撤销调拨区域的物理存储器大小,并传入MEM_DECOMMIT给fdwFreeType。
和调拨物理存储器一样,撤销调拨也是基于页面粒度的。也就是说,如果给定的地址位于一个页面中,那么系统会撤销调拨整个页面。如果dwSize为0,而pvAddress又是该区域的基地址,那么VirtualFree会调拨给该区域的所有页面。
改变保护属性
实际中我们很少需要改变已调拨物理存储器的保护属性。比如,我们可以写一个管理链表的程序,把链表中的节点保存在一个已预订的区域中。我们可以设计这样的链表处理函数,让它们在每个函数的开头把物理存储器的保护属性改成PAGE_READWRITE,访问后,再把保护属性改回FPAGE_NOACCESS。这样就可以保护链表数据免受程序中其他缺陷的影响。
我们可以调用VirtualProtect函数来改变一个内存页面的保护属性:
BOOL VirtualProtect( PVOID pvAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD pflOldProtect); |
pvAddress指向内存基地址。
dwSize表示要改变保护区域的大小,以字节为单位。
flNewProtect可以是除了PAGE_WRITECOPY和PAGE_EXECUTE_WRITECOPY之外的任何PAGE_*属性。
pflOldProtect是一个指针,返回原来的属性。一定不可以传入NULL,必须传入一个有效的地址给VirtualProtect,否则函数执行失败。
由于保护属性是与整个物理存储页相关联的,VirtualProtect会改变pvAddress和dwSize跨越的所有页面的属性。而不会仅仅对一个字节改变属性,这是没有意义的。
重置物理存储器的内容
当我们修改物理内存页时,系统会尽量把改动把持在内存中。当应用程序在运行时,可能需要将数据载入内存,系统会在内存中查找可用的页面。如果找到闲置页面,就将数据载入此页面。如果没有找到,系统就会采用一定的算法,置换一些页面。如果该页面已经被修改过,系统会将这些页面置换到页交换文件。
Windows提供一项特性,使得应用程序能够提高自身的性能。这一特性就是重置物理存储器。重置物理存储器的意思是告诉系统一个或几个物理存储器页中数据没有被修改过。在需要闲置页面时,可以直接将它们覆盖,而不需要将它们写入页交换文件。有些应用程序需要在一小段时间内使用存储器,之后就不需要保存存储器中的内容。为了提高性能,应用程序应该告诉系统此页面没有被修改过,不要在页交换文件中保存存储页。
为了重置存储器,应用程序应该调用VirtualAlloc函数并在第二个参数中传MEM_RESET标志。
PINT pnData=(PINT)VirtualAlloc(NULL,1024, MEM_RELEASE|MEM_COMMIT,PAGE_READWRITE); pnData[0]=100; pnData[1]=200; VirtualAlloc((PVOID)pnData,sizeof(int),MEM_RESET,PAGE_READWRITE); |