Reserves, commits, or changes the state of a region of pages in the virtual address space of the calling process. Memory allocated by this function is automatically initialized to zero.
LPVOID WINAPI VirtualAlloc( _In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect );
为了更好的理解VirtualAlloc,我们需要先了解下虚拟内存技术原理。
Windows的内存结构是深入理解Windows操作系统如 何运作的最关键之所在,通过对内存结构的认识可清楚地了解诸如进程间数据的共享、对内存进行有效的管理等问题,从而能够在程序设计时使程序以更加有效的方 式运行。Windows操作系统对内存的管理可采取多种不同的方式,其中虚拟内存的管理方式可用来管理大型的对象和结构数组。
在Windows系统中,任何一个进程都被赋予其自己的虚拟地址空间,该虚拟地址空间覆盖了一个相当大的范围,对于32位进程,其地址空间为 2^32=4,294,967,296 Byte,这使得一个指针可以使用从0x00000000到0xFFFFFFFF的4GB范围之内的任何一个值。虽然每一个32位进程可使用4GB的地址 空间,但并不意味着每一个进程实际拥有4GB的物理地址空间,该地址空间仅仅是一个虚拟地址空间,此虚拟地址空间只是内存地址的一个范围。进程实际可以得到的物理内存要远小于其虚拟地址空间。进程的虚拟地址空间是为每个进程所私有的,在进程内运行的线程对内存空间的访问都被限制在调用进程之 内,而不能访问属于其他进程的内存空间。这样,在不同的进程中可以使用相同地址的指针来指向属于各自调用进程的内容而不会由此引起混乱。
在进程创建之初并被赋予地址空间时,其虚拟地址空间尚未分配,处于空闲状态。这时地址空间内的内存是不能使用的,必须首先通过VirtualAlloc()函数来分配其内的各个区域,对其进行保留。
其参数lpAddress包含一个内存地址,用于定义待分配区域的首地址。通常可将此参数设置为NULL,由系统通过搜索地址空间来决定满足条件的未保留 地址空间。这时系统可从地址空间的任意位置处开始保留一个区域,而且还可以通过向参数flAllocationType设置MEM_TOP_DOWN标志 来指明在尽可能高的地址上分配内存。如果不希望由系统自动完成对内存区域的分配而为lpAddress设定了内存地址(必须确保其始终位于进程的用户模式分区中,否则将会导致分配的失败), 那么系统将在进行分配之前首先检查在该内存地址上是否存在足够大的未保留空间,如果存在一个足够大的空闲区域,那么系统将会保留此区域并返回此保留区域的 虚拟地址,否则将导致分配的失败而返回NULL。这里需要特别指出的是,在指定lpAddress的内存地址时,必须确保是从一个分配粒度的边界处开始。
内存的“保留”与“提交”:
Win32为系统中的每一个应用程序(进程)提供一个独立的、2 GB的用户地址空间。对于应用程序来说,好象是有2 GB的可用内存(实际上在Windows95/98,NT,Win2000 Advanced Server/Enterprise Server 上的内存分配略有不同),而不用考虑实际可用的物理内存的量。如果某个应用程序要求的内存比可用的内存更多时,Win32是这样满足这种要求的,它从这个 和/或其他的进程把非关键内存分页(paging)到一个页文件,并且释放这些物理内存页。
在任意给定的时间,进程中每个地址都可以被当作是自由的、保留的或已提交的。进程开始时,所有地址的都是自由的,意味着它们都是自由空间并且可以被提交到 内存,或者为将来使用而保留起来,但是它们不能存取(read/write)。在任何自由的地址能够被使用前,它必须首先被分配为保留的或已提交的。
当在一个进程中保留地址时,没有物理内存页被提交,并且,也许更为重要的是,在页文件中没有为备份该内存而保留空间。而且,保留一个地址范围将不会保证将来会有可用的物理内存来提交给这些地址。实际上,它只是保存了一个指定的自由地址地址,一直到需要使用它时,而阻止了其它分配对该段地址的请求。如果没有 这种类型的保护,那么例程操作(routine operations),例如加载一个DLL或者资源,可能会占有指定的地址,并且危害以后对它的使用。 要使用保留的地址,内存首先必须被提交给该地址。提交内存到地址与保留内存相类似.调用VirtualAlloc,并且在调用时设置 dwAllocation参数等于MEM_COMMIT。在这一时刻,资源被提交到地址上。每一次,内存可以按一页的大小被提交。能够被提交的最大内存值 仅仅取决于连续的自由或者保留地址的最大范围(但两者不可组合在一起),无须考虑系统的可用物理内存的大小。
当内存被提交时,内存物理页被分配,并且该段空间被保留在在一个页文件中。也就是说,已提交的内存页总是以物理内存页或者在已经被分页的磁盘上的页文件的 形式存在。当提交一个大块内存时,在初始阶段,其部分或者全部内存没有驻留在物理内存中也是有可能的。某些内存页一开始驻留在页文件中,直到它被访问。在 系统中,一旦内存页已提交,虚拟内存管理器象对待所有其它的内存页一样对待它们。
在Win32虚拟内存系统中,使用了页表(page
tables)来访问物理内存页。每个页表本身也是一个内存页,象已提交的页一样。偶而,当提交内存时,同时还必须对页表分配附加的页。所以,提交一页内
存的请求可能需要为页表分配一页,为请求的页分配一页,并且在页文件中需要两页空间来备份这些页中的每一页。因此,VirtualAlloc完成一个内存
提交请求所需要的时间变化很大,它取决于系统的状态以及请求的空间大小。
“内存 - 提交大小:为某进程使用而保留的虚拟内存的数量。
对于已提交的页面,系统会根据总的内存使用情况来调度它们。当物理内存紧张时,系统会选择一些页面,将它们换出到内存文件中,待下次使用的时候,再将它们
换回来。通常情况下,应用程序并不需要干预系统的页面调度机制。在一些特殊情况下,应用程序也可以通过VirtualLock函数来锁住已提交页面,使得
它们总是留在物理内存中;以后再调用VirtualUnlock函数来结束这种锁定。”
关键字:
内存保留 内存提交
参考:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366887%28v=vs.85%29.aspx
http://www.yesky.com/67/1753067.shtml
http://super-man-woman.blog.163.com/blog/static/3789803820098532317144/