5.1 Windows内存管理

http://book.51cto.com  2010-06-03 11:51  冯宏华/徐莹 等  电子工业出版社  我要评论(0)
第5章 操作系统的内存管理
长期以来,在计算机系统中,内存都是一种紧缺和宝贵的资源,应用程序必须在载入内存后才能执行。以前,在内存空间不够大时,同时运行的应用程序的数量就会受到很大限制。甚至当某个应用程序在某个运行时所需内存超过物理内存时,该应用程序就会无法运行。现代操作系统(诸如Windows和Linux)的内存管理都能解决这个问题,解决的方法就是虚拟内存的引入。
本质上虚拟内存就是要让一个程序的代码和数据在没有全部载入内存时即可运行。运行过程中,当执行到尚未载入内存的代码,或者要访问还没有载入到内存的数据时,虚拟内存管理器动态地将这部分代码或数据从硬盘载入到内存中。而且在通常情况下,虚拟内存管理器也会相应地先将内存中某些代码或者数据置换到硬盘中,为即将载入的代码或数据腾出空间。
因为内存和硬盘之间的数据传输相对代码执行来说,是非常慢的操作,因此虚拟内存管理器在保证工作正确的前提下,还必须考虑效率因素。比如,它需要优化置换算法,尽量避免就要执行的代码或访问的数据刚被置换出内存,而很久没有访问的代码或数据却一直驻留在内存中。另外它还需要将驻留在内存的各个进程的代码或数据维持在一个合理的数量上,并且根据该进程的性能表现动态调整此数量,等等,使得程序运行时将其涉及的磁盘I/O次数降到尽可能低,以提高程序的运行性能。
本章前一部分着重介绍Windows的虚拟内存管理机制,后一部分则简要介绍Linux的虚拟内存管理机制。
5.1  Windows内存管理
如果从应用程序的角度来看Windows虚拟内存管理系统,可以扼要地归结为一句话。即Win32虚拟内存管理器为每一个Win32进程提供了进程私有且基于页的4 GB(32位)大小的线性虚拟地址空间,这句话可以分解如下:
(1)"进程私有"意味着每个进程都只能访问属于自己的地址空间,而无法访问其他进程的地址空间,也不用担心自己的地址空间会被其他进程看到(父子进程例外,比如调试器利用父子进程关系来访问被调试进程的地址空间,这里不详述)。需要注意的是,进程运行时用到的dll并没有属于自己的虚拟地址空间。而是其所属进程的虚拟地址空间,dll的全局数据,以及通过dll函数申请的内存都是从调用其进程的虚拟地址空间中开辟的。
(2)"基于页"是指虚拟地址空间被划分为多个称为"页"的单元,页的大小由底层处理器决定,x86中页的大小为4 KB。页是Win32虚拟内存管理器处理的最小单元,相应的物理内存也被划分为多个页。虚拟内存地址空间的申请和释放,以及内存和磁盘的数据传输或置换都是以页为最小单位进行的。
(3)"4 GB大小"意味着进程中的地址取值范围可以从0x00000000到0xFFFFFFFF。Win32将低区的2 GB留给进程使用,高区的2 GB则留给系统使用。
Win32中用来辅助实现虚拟内存的硬盘文件称为"调页文件",可以有16个,调页文件用来存放被虚拟内存管理器置换出内存的数据。当这些数据再次被进程访问时,虚拟内存管理器会先将它们从调页文件中置换进内存,这样进程可以正确访问这些数据。用户可以自己配置调页文件。出于空间利用效率和性能的考虑,程序代码(包括exe和dll文件)不会被修改,所以当它们所在的页被置换出内存时,并不会被写进调页文件中,而是直接抛弃。当再次被需要时,虚拟内存管理器直接从存放它们的exe或dll文件中找到它们并调入内存。另外对exe和dll文件中包含的只读数据的处理与此类似,也不会为它们在调页文件中开辟空间。
当进程执行某段代码或者访问某些数据,而这些代码或者数据还没有在内存时,这种情形称为"缺页错误"。缺页错误的原因有很多种,最常见的一种就是已经提到的,即这些代码和数据被虚拟内存管理器置换出了内存,这时虚拟内存管理器在这段代码执行或者这些数据被访问前将它们调入内存。这个操作对开发人员来说是透明的,因此大大简化了开发人员的负担。但是调页错误涉及磁盘I/O,大量的调页错误会大大降低程序的总体性能。因此需要了解缺页错误的主要原因,以及规避它们的方法。
【责任编辑:云霞 TEL:(010)68476606】