Windows的内存管理方法
windows提供了3种方法来进行内存管理:
l 虚拟内存,最适合用来管理大型对象或者结构数组
l 内存映射文件,最适合用来管理大型数据流(通常来自文件)以及在单个计算机上运行多个进程之间共享数据。
l 内存堆栈,最适合用来管理大量的小对象。
1 虚拟内存
虚拟内存的使用主要有以下几个步骤:
1. 在地址空间保留一个区域,调用函数VirtualAlloc
2. 在保留区域中的提交物理存储器,当保留一个区域后,必须将物理存储器提交给该区域,然后才能访问该区域中包含的内存地址。系统从它的页文件中将已提交的物理存储器分配给一个区域。仍旧调用函数VirtualAlloc具体参数设置可以见msdn,当然,用户也可以一次性地进行操作保留区域和提交物理存储器。
3. 回收虚拟内存和释放地址空间区域,调用VirtualFree函数,并且,如果要释放一个区域,必须释放该区域保留地所有地址空间。当然用户也可以只回收物理存储器而不释放区域,仍旧调用VirtualFree函数,但参数传入不同。
2 内存映射文件
与虚拟内存一样,内存映射文件可以用来保留一个地址空间的区域,并将物理存储器提交给该区域。他们之间的区别是,物理存储器来自一个已经位于磁盘上的文件,而不是系统的页文件。一旦该文件被映射,就可以访问它,就像整个文件被加载到了内存一样。
内存映射文件一般用于3个不同的目的:
1. 系统使用内存映射文件,以便加载和执行.exe和DLL文件。这可以大大节省页文件空间和应用程序启动运行所需的时间
2. 可以使用内存映射文件来访问磁盘上的数据文家爱女。这使你可以不比对文件执行i/o操作,并且可以不必对文件内容进行缓存
3. 可以使用内存映射文件,使同一台计算机上运行的多个进程能够相互之间共享数据。
若要使用内存映射文件,必须执行下列操作步骤:
1) 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件 (CreateFile函数)
2) 创建一个文件映射内核对象,告诉系统该文件的大小和你打算如何访问该文件
(CreateFileMapping函数)
3) 让系统将文件映射对象的全部或一部分映射到你的地址空间
(MapViewOfFile函数,要求文件的位移是分配粒度的倍数)
当完成对内存映射文件的使用时,必须执行下面的这些步骤将它清除:
4)告诉系统从你的进程的地址空间中撤销文件映射内核对象的映象
(UnmapViewOfFile函数)
5)关闭文件映射内核对象
(CloseHandle函数,第2)步创建的对象)
6)关闭文件内核对象
(CloseHandle函数,第1)步创建的对象)
利用内存映射文件,还可以实现进程之间的数据共享。数据共享的方法是通过让两个或多个进程映射同一个文件映射对象的视图,这也意味着他们将共享物理存储器的同一个页面。另外,用户也可以创建由系统的页文件支持的内存映射文件,而不是由专用硬盘文件支持的内存映射文件。这样,就不需要调用CreateFile函数,只需要给CreateFileMapping的Hfile参数传递INVALID_HANDLE_VALUE,并传递一个以0结尾的字符串作为pszName参数。别的进程就可以用CreateFileMapping或者OpenFilemapping函数。
3 堆栈
堆栈可以用来分配许多较小的数据块,例如对链接表和链接树进行管理等。堆栈的优点是,可以不考虑分配粒度和页面边界之类的问题。堆栈的缺点是,分配和释放内存块的速度比其他机制要慢,并且无法直接控制物理存储器的提交和回收。
当进程初始化时,系统在进程的地址空间中创建一个堆栈。该堆栈为进程的默认堆栈。按照默认设置,该堆栈的地址空间区域的大小是1MB。系统可以扩大进程的默认堆栈。由于进程的默认堆栈可以供许多windows函数调用,因此对默认堆栈的访问是按顺序进行的。也就是,系统必须保证在规定的时间内,每次只有一个线程能分配和释放默认堆栈中的内存块 。当然,用户也可以在进程的地址空间中创建一些辅助堆栈。
堆栈的一些操作函数如下(具体可以查msdn):
1.创建堆栈 HeapCreate
2. 从堆栈中分配内存块 HeapAlloc
3. 改变内存块的大小 HeapReAlloc
4. 释放内存块 HeapFree
5. 撤销堆栈 HeapDestroy