预定区域: LPVOID WINAPI VirtualAlloc( __in_opt LPVOID lpAddress,//希望预定的地址空间,大多数时候传递NULL就行。系统会按照分配粒度(64K)的整数倍来分配, 成功返回地址,失败返回NULL,如果地址参数不在用户模式分区中函数会失败并且返回NULL。 __in SIZE_T dwSize,//希望预定的区域大小,字节为单位,始终根据CPU页面大小的整数倍来预定,如果在页面大小为4KB、 8KB、16KB的机器上预定62KB的区域,最终得到的都是64KB。 __in DWORD flAllocationType,//是预定区域还是调拨物理存储器。预定:MEM_RESERVE,如果预定的区域将用很长时间, 可以传递NULL给lpAddress,此标志位设为MEM_TOP_DOWN|MEM_RESERVE来从高内存地址来预定区域,防止内存碎片。 __in DWORD flProtect//区域的保护属性,通常用PAGE_READWRITE。对调拨给该区域的物理存储器不起作用。可以使用的保护属性: PAGE_NOACCESS,PAGE_READWRITE,PAGE_READONLY,PAGE_EXECUTE,PAGE_EXECUTE_READ,PAGE_EXECUTE_READWRITE。 如果使用PAGE_WRITECOPY或者PAG_EXECUTE_WRITECOPY,该函数将不会预定区域,并且返回NULL, 在预定区域的时候也不能后使用PAGE_GUARD,PAGE_NOCACHE,PAGE_WRITECOMBINE,这些只能用来调拨物理存储器。 );
调拨存储器:在预定区域 之后,需要调拨物理存储器才能访问其中大多内存地址,系统会从页面交换文件中调拨物理存储器给区域。
其实位置始终是页面大小的整数倍,
LPVOID WINAPI VirtualAlloc( __in_opt LPVOID lpAddress,//可以从预定的区域中选取一部分来调拨物理存储器,传递实际需要调拨的地址 __in SIZE_T dwSize,//需要调拨的区块大小,会进行对齐 __in DWORD flAllocationType,//MEM_COMMIT __in DWORD flProtect//通常设置跟预定区域的属性相同,通常是PAGE_READWRITE );
同时预定和调拨物理存储器:
PVOID pvMem = VirtualAlloc(NULL, 99*1024, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
系统会先搜索进程的地址空间,找到一块足够大的闲置地址空间,会对页面大小进行上对齐,
如果指定了pvAdress,系统会检查地址,如果没有空闲地址空间函数返回NULL。
在处理类似于较大表格的时候可以预定一块较大的区域,当用户在某块区域写入数据的时候,定位掉区域的内存地址进行调拨存储器,可以加快速度。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
撤销调拨的物理存储器
LPVOID WINAPI VirtualFree( __in_opt LPVOID lpAddress,//必须是VirtualAlloc返回的基地址 __in SIZE_T dwSize,//设为0 __in DWORD flAllocationType,//MEM_RELEASE );撤销调拨给区域的一部分物理存储器,不释放整个区域,撤销是基于整个页面,如果lpAddress或者lpAddress+dwSize在一个页面中间,
将撤销整个地址区间的页面,撤销调拨给页面的物理存储器将被释放与其他进程
BOOL WINAPI VirtualFree( __in LPVOID lpAddress,//撤销调拨的第一个页面地址 __in SIZE_T dwSize,//希望释放的物理存储器大小 __in DWORD dwFreeType//MEM_DECOMMIT );