<>第15~18章内存管理

时间:2021-06-03 20:41:28

Windows提供了以下三种机制来对内存进行操控:

虚拟内存:最适合用来管理大型对象数组或大型数据结构数组

内存映射文件:最适合用来管理大型数据流(通常是文件),以及在同一机器上运行的多个进程之间共享数据

堆:最适合用来管理大量的小型对象


线程栈:

当系统创建线程时,会为线程栈预定一块地址空间区域(每个线程都有自己的栈),并给区域调拨一些物理存储器。默认的情况下,系统会预定1MB的地址空间并调拨两个页面的存储器。以基地址为0x08000000为例说明线程栈的内存分配:

在预定地址空间区域后,系统会给区域顶部(即地址最高)的两个页面调拨物理存储器。在让线程开始执行前,系统会把线程栈的指针指向区域顶部的那个页面的末尾(该地址应该是0x08100000-0x00001000(4KB)=0x080FF000)。这个页面就是线程开始使用线程栈的地方。区域顶部往下的第二个页面也被称为防护页面(guard page),随着线程调用越来越多的函数,调用数也越来越深,线程也需要越来越多的栈空间。

但线程试图访问防护页面中的内存时,系统会得到通知。这时系统会先给防护页面下面的那个页面调拨存储器,接着去除当前防护页面的PAGE_GUARD保护属性标志,然后给刚调拨的存储页指定PAGE_GUARD保护属性标志。该项技术使得系统能够在线程需要的时候才增大存储器的大小。如果线程的调用树不断加深,那么栈的地址空间区域的PAGE_GUARD逐渐接近基地址0x08000000。

当页面分配到0x08001000时候,系统会去除地址为0x08002000的页面的PAGE_GRARD保护属性标志,然后给地址为0x08001000的页面调拨物理存储器。区别在于系统不会给刚调拨的物理存储器(地址为0x08001000)指定防护属性。这意味着栈的地址空间区域已经放满了它所能容纳得下的所有物理存储器。系统永远不会给区域底部的那个页面调拨存储器。