1. 进程中,最重要的一条特性:每个进程都拥有自己”私有”的4GB虚拟地址空间.
每个进程的内存空间包含各种各样的内容,其中有:
● 程序的EXE镜像
● 程序中装入的非系统的DLL,包括MFC DLL
● 程序的全局数据(只读和可读写的)
● 程序的堆栈
● 动态分配的内存,包括Windows和C运行库(CRT)堆
● 内存映射文件
● 进程之间共享的内存块
● 特定执行线程的局部内存
● 所有各种系统内存块,包括虚拟内存表
● Windows核心、执行过程及DLL,它们是Windows的一部分
2.在Windows 95中只有底下的2GB(0-0x7FFFFFFF)地址空间是真正私有的.而其中最底下的4MB是进制访问的.堆栈、堆和可读写的全局内存,及其应用程序的EXE和dll文件都被映射到底层的2GB地址上.
3. 虚拟内出的工作原理:
首先,进程的4GB地址空间不是被全部用到,各种程序和数据被分散到4GB地址空间里(即所谓的分页技术),以4KB为界,每个单元为4KB大小.它可以存放数据和代码.Intel微处理器芯片可以有效的把一个32位虚拟地址映射到物理页面和页面中的偏移,它使用了两级4KB页表,一个页表可以是只读和可读写状态.每个进程也都有他自己的一组页表.
然后通过一个标志位来判断4KB是否在内存中.它将根据实际情况来处理.
所有的进程共享一个大的系统交换文件,用于所有可读写数据和一些只读数据.交换文件并不是虚拟内存管理器使用的唯一的文件,.如果两个进程使用同一个EXE文件,则该文件将被映射到每个进程的物理空间.
4. 堆是特定进程的内存池.当程序需要内存块时,他调用堆分配函数,并调用相关的函数释放内存.
Windows为每个进程提供一个缺省堆,进程也可以创建一些附加的Windows堆.函数HeapAlloc在一个Windows堆里分配内存,HeapFree释放内存.
GlobalAlloc使用了缺省Windows堆,他根据其属性参数做两件不同的事情.
① 如果参数指定了GMEM_FIXED,则GlobalAlloc简单的调用HeapAlloc,把返回地址作为一个32位HGLOBAL值;
② 如果指定了GMEM_MOVEABLE,则返回的HGLOBAL值是一个指向进程里句柄表中某项入口的指针.该入口包含了指向实际HeapAlloc分配的内存地址指针.
5. 如果使用new分配的内存块大于一个特定的值(480字节),则CRT将直接调用HeapAlloc从为CRT创建的Windows队中分配内存;对于小于480个字节的内存块堆,必要时需要调VirtualAlloc和VirtualFree,相应的算法如下:
① 按4MB的区域保留内存
② 按64KB的块占用内存
③ 每次收回64KB内存,当128KB内存被释放时,最后的64KB被收回
④ 当4MB内存区域里每页都被收回时,内存区域被释放
6. 不要忘记在每次我们的程序分配大于小内存堆(480字节)是调用_heapmin函数.同时也要小心记住堆内存的来源.(即要对应来使用)
7. 内存分配空间图谱
名称 | 类型 | 存取方式 | 内容 |
.text | 代码 | 只读 | 程序代码 |
.rdata | 数据 | 只读 | 常量初始化数据(是EXE文件的一部分 |
.data | 数据 | 读/写 | 非常量的初始化数据 |
.bas | 数据 | 读/写 | 非常量未初始化数据 |