1第5章windows内存管理•Windows内存体系结构•在应用程序中使用虚拟内存•内存映射文件•堆2存储体系•高速缓存:–DataCache–TLB(TranslationLookasideBuffer)•内存:DRAM,SDRAM等;•外存:软盘、硬盘、光盘、磁带等;外存(secondarystorage)DOS核心命令处理程序内存(primarystorage)高速缓存(cache)寄存器(register)3虚拟地址和物理地址•虚拟地址(相对地址,逻辑地址):用户的程序经过汇编或编译后形成目标代码,目标代码通常采用相对地址的形式。–其首地址为0,其余指令中的地址都相对于首地址来编址。–不能用逻辑地址在内存中读取信息。•物理地址(绝对地址,实地址):内存中存储单元的地址。物理地址可直接寻址。•地址映射:将用户程序中的逻辑地址转换为运行时由机器直接寻址的物理地址。–当程序装入内存时,操作系统要为该程序分配一个合适的内存空间,由于程序的逻辑地址与分配到内存物理地址不一致,而CPU执行指令时,是按物理地址进行的,所以要进行地址转换。4地址映射BA=10003456。。。1200物理地址空间movax,data1data13456源程序movax,[200]34560100200编译连接虚拟地址空间逻辑地址和物理地址movax,[1200]100011005地址映射BA=10003456。。。1200物理地址空间movax,[200]34560100200虚拟地址空间逻辑地址和物理地址-movax,[1200]10001100内存管理单元(MMU)重定位寄存器65.0内存管理基础理论复习7•连续分配内存管理•基本分页内存管理•基本分段内存管理•段页式内存管理•虚拟存储管理•Windows借助硬件机制实现了段页式内存管理和虚拟存储管理。85.1windows内存体系结构95.1.1进程的虚地址空间•每个进程都有自己的虚地址空间.–32位进程:4GB(0x00000000-0xFFFFFFF)–64位进程:16EB(0x00000000‘00000000-0xFFFFFFFF’FFFFFFFF)105.1.2虚地址空间的分配•每个进程的虚地址空间都要划分成多个分区。地址空间的分区依赖操作系统的的底层实现。不同的Windows内核会略有不同。[我们主要介绍x86-32位进程]2G2G11(1)Null-PointerAssignmentPartition(空指针赋值分区)•地址空间:0x00000000to0x0000FFFF•如果进程中的线程试图读取该分区的地址空间的数据,或者将数据写入该分区的地址空间,那么CPU就会引发一个访问违规。•此分区的目的:帮助程序员捕获对NULL指针操作错误。例如:int*pIPoint=(int*)malloc(sizeof(int));….(1)*pIPoint=3;….(2)如果malloc无法分配足够内存,它返回NULL,于是语句(2)违规.12(2)User-ModePartition(用户模式分区)•这个分区是进程的私有(非共享)地址空间所在的地方。对于所有应用程序来说,该分区是维护进程的大部分数据的地方。•所有的.exe和DLL模块均加载这个分区。•系统还可以在这个分区中映射该进程可以访问的所有内存映射文件。13我们可以看到:•x86-32位进程可用的地址空间只有大约2G,还有2G呢?给了Kernel。为什么?–操作系统需要这个大约2G地址空间,供内核代码、设备驱动程序代码、设备I/O高速缓存、非页面内存池的分配和进程页面表等使用。实际上Microsoft将内核压缩到这个2GB空间之中。14(3)64-KBOff-Limits(64KB禁止进入的分区)•这个位于用户方式分区上面的64KB分区是禁止进入的,访问该分区中的内存的任何企图均将导致访问违规。Microsoft之所以保留该分区,是因为这样做将使得Microsoft能够更加容易地实现操作系统。15(4)Kernel-ModePartition(内核模式分区)•这个分区是存放操作系统代码的地方。用于线程调度、内存管理、文件系统支持、网络支持和所有设备驱动程序的代码全部在这个分区加载。驻留在这个分区中的一切均可被所有进程共享。在Windows2000/xp/2003中,这些组件是完全受到保护的。16•x86-32位机内核空间(2GB)进程1的用户空间(约2GB)进程2的用户空间(约2GB)进程n的用户空间(约2GB)虚拟地址空间64-KBOff-Limits64-KBOff-Limits64-KBOff-Limits64-KBOff-LimitsNull-PointerAssignmentNull-PointerAssignmentNull-PointerAssignmentNull-PointerAssignment175.1.3虚地址空间中的区域•当一个进程创建并分配了虚地址空间后,大部分可用的地址是空闲的(一个2G的程序是很少的)。•如果进程需要使用这部分空闲的地址空间,就必须调用win32的VirtualAlloc函数来分配区域,称为预定、保留(reserving).•区域(Region)的单位多少?为什么?–所有CPU使用相同的分配单元-64KB–刚好是页大小的整数倍,win32X86的页大小是4KB–页是系统管理内存的单位•当程序的算法不需要访问该区域时,使用VirtualFree释放。1页(4K)0页(4K)…15页(4K)1个区域18•区域的状态有:空闲、私有、映射、映像。–默认情况下,区域状态是空闲;–在程序里预订了地址空间以后,你还不可以存取数据,因为你还没有付钱,没有真实的RAM和它关联,这时候的区域状态是私有;–当.exe或DLL文件被映射进了进程空间后,区域状态变成映像;–当一般数据文件被映射进了进程空间后,区域状态变成映射。195.1.4在区域内提交物理存储•要使用虚地址空间的预定区域,就必须分配物理存储,即进行提交。•物理存储总是以页为单位提交。•提交时,并不是整个区域提交,只是提交当前需要页。•提交和释放函数:VirtualAlloc,VirtualFree1页(4K)0页(4K)…15页(4K)2页(4K)物理存储205.1.5物理存储器与页文件•现代的操作系统能够使得磁盘空间看上去就像内存一样。磁盘上的文件通常称为页文件,它包含了可供进程使用的虚拟内存。•即页文件(pagefile.sys)也称虚拟内存。就是在硬盘上拿出一部分空间作为暂不被调用进程或叫“惰性”进程及相关数据的临时存放空间。解释原理(PhysicalStorageandthePagingFile)21•因RAM容量总是有限,而实际运行的进程会很多,若都塞在RAM中会大量占用有限的内存资源,不利于系统正常、快速、流畅地调用、运行急需的进程及数据。于是系统就开辟出一部分硬盘空间将惰性进程及相关数据暂时存放于此,而让即将被调用的进程或称“活性”进程及数据存留在RAM中方便马上调用;而页面文件中暂存的“惰性”进程及数据待CPU需要调用时再与RAM交互。•页文件如同文件夹中常见文件一样,是实实在在存在的文件,只是为安全起见系统将其默认为隐藏文件,显示后一般可在系统盘根目录中见到名为pagefile.sys的文件,它就是页文件。•页文件最好单独设置在一个盘符里,如此能使系统调用虚拟内存中的程序及数据时能更快速、更流畅。还有,变更页文件的位置之前最好能对相应盘符进行磁盘碎片整理,以使页文件连续、规律地存放利于快速读取。22•若要使虚拟内存能够运行,需要得到CPU的大量帮助。当一个线程试图访问一个字节的内存时,CPU必须知道这个字节是在RAM中还是在磁盘上。•从应用程序的角度来看,页文件透明地增加了应用程序能够使用的RAM(即内存)的数量。–例如:如果计算机拥有64MB的RAM,同时在硬盘上有一个100MB的页文件,那么运行的应用程序就认为计算机总共拥有164MB的RAM.23虚拟地址虚地址到物理地址转换RegionPageRAM页文件(虚拟内存)24将虚拟地址转换成物理存储器地址的流程页面的数据是否已修改?25•系统的页文件(pagefile.sys)的大小是确定有多少物理存储器可供应用程序使用时应该考虑的最重要的因素.•但是,系统将页文件拷贝到内存页面的次数越多,你的硬盘倒腾的次数就越多,系统运行得越慢。•所以必须遵循一条基本原则,那就是要让你的计算机运行得更块,增加更多的RAM。实际上,在大多数情况下,若要提高系统的运行性能,增加RAM比提高CPU的速度所产生的效果更好。265.1.6保护属性•已经分配的物理存储器的各个页面可以被赋予不同的保护属性。见下表:注意:x86和AlphaCPU不支持“执行”保护属性。27Copy-On-Write访问•PAGE_WRITECOPY和PAGE_EXECUTE_WRITECOPY两个属性的作用是为了节省RAM的使用量和页文件的空间。Windows支持一种机制,使得两个或多个进程能够共享单个内存块。这样所有实例可以共享应用程序的代码和数据页面,大大提高系统的性能。但是这要求所有实例都将该内存视为只读或只执行的内存,否则会造成一片混乱。•为了防止出现这种混乱,操作系统给共享内存块赋予了Copy-On-Write访问属性。当一个.exe或DLL模块被映射到一个内存地址时,系统将计算有多少页面是可以写入的(通常包含代码的页面标为PAGE_EXECUTE_READ,而包含数据的页面则标为PAGE_READWRITE)。然后,系统从页文件中分配内存,以适应这些可写入的页面的需要。28•当一个进程中的线程试图将数据写入一个共享内存块时,系统就会进行干预,并执行下列操作步骤:–1)系统查找RAM中的一个空闲内存页面。注意,当该模块初次被映射到进程的地址空间时,该空闲页面将被页文件中已分配的页面之一所映射。当该模块初次被映射时,由于系统要分配所有可能需要的页文件,因此这一步不可能运行失败。–2)系统将试图被修改的页面内容拷贝到第一步中找到的页面。该空闲页面将被赋予PAGE_READWRITE或PAGE_EXECUTE_READWRITE保护属性。原始页面的保护属性和数据不发生任何变化。–3)然后系统更新进程的页面表,使得被访问的虚拟地址被转换成新的RAM页面。当系统执行了这3个操作步骤之后,该进程就可以访问它自己的内存页面的私有实例.295.2在应用程序中使用虚拟内存30•Windows提供了3种进行内存管理的方法,它们是:–虚拟内存(pagefile.sys),最适合用来管理大型对象或结构数组。–内存映射文件,最适合用来管理大型数据流(通常来自文件)以及在单个计算机上运行的多个进程之间共享数据。–内存堆栈,最适合用来管理大量的小对象。•本节介绍第一种方法,即虚拟内存。31•用于管理虚拟内存的函数可以用来:–直接预定一个地址空间区域,–将物理存储器(来自页文件)提交给该区域,并且可以设置你自己的保护属性。325.2.1在地址空间中预定一个区域•通过调用VirtualAlloc函数,可以在进程的地址空间中预定一个区域:33•lpAddress:内存地址,用于设定想让系统将地址空间预定在什么地方。多数情况下,传递NULL;•dwSize:用于设定想预定的区域的大小,以字节为单位。注意:系统保留的区域始终是CPU页面大小的倍数。•flAllocationType:告诉系统你想预定一个区域还是提交物理存储器。[MEM_RESERVE或MEM_COMMIT]•flProtect:于指明应该赋予该地址空间区域的保护属性.注意:不能设定PAGE_WRITECOPY或PAGE_EXECUTE_WRITECOPY属性,如果设定了这些属性,函数将不预定该区域,并且返回NULL。345.2.2给区域提交(调拨)物理存储器•在预定区域后,还需要给区域调拨物理存储器,这样才能访问其中的内存地址;•系统从页文件(pagefile