虚拟内存管理总结

  操作系统为每一个进程维护着一个虚拟的地址空间,这个地址空间的大小通常取决于系统的地址线数目,比如在32位系统中,虚拟地址空间的返回就是0×00000000~0xFFFFFFFF,大小共4G。通常操作系统会划分出一部分来专门供内核使用,而不允许用户进程直接访问。Linux内核占用4G中高地址的1G,即0XC0000000~0XFFFFFFFF,windows内核通常占用高地址的2G空间,但也可配置成1G。进程的代码、数据以及共享库等资源终究是要放在物理内存中才能被访问的,操作系统在建立用户进程时,会为其建立各自独立的虚拟地址空间,然后将各自的数据段、代码段、BSS段等映射到这个地址空间,并为其初始化堆、栈等必须的资源。另外,操作系统还将虚拟空间和物理空间都划分成大小相等的页,把进程数据所在虚拟地址空间的各个虚拟页面映射到其真正被加载的物理页面,这种映射是全相联方式的,即任何一个虚页可以被映射到任何一个实页。

  操作系统采用虚拟内存的方式管理存储器有很多好处:

  第一,虚拟内存管理可以控制物理内存的访问权限。物理内存本身是不限制访问的,任何地址都可以读写,而操作系统要求不同的页面具有不同的访问权限,这是利用CPU模式和MMU的内存保护机制实现的。例如,代码段被只读保护起来,防止被错误的指令意外改写,内核地址空间也被保护起来,防止在用户模式下执行错误的指令意外改写内核数据。这样,执行错误指令或恶意代码的破坏能力受到了限制,顶多使当前进程因段错误终止,而不会影响整个系统的稳定性。

  第二,虚拟内存管理最主要的作用是让每个进程有独立的地址空间。所谓独立的地址空间是指,不同进程中的同一个VA被MMU映射到不同的PA,并且在某一个进程中访问任何地址都不可能访问到另外一个进程的数据,这样使得任何一个进程由于执行错误指令或恶意代码导致的非法内存访问都不会意外改写其它进程的数据,不会影响其它进程的运行,从而保证整个系统的稳定性。另一方面,每个进程都认为自己独占整个虚拟地址空间,这样链接器和加载器的实现会比较容易,不必考虑各进程的地址范围是否冲突。

  第三,方便了共享库的实现。采用共享库的目的在于节省内存(物理内存),一些公用模块在内存中可以只保存一份,让各进程共享,而不是各自加载一份,当然,只读的代码段可以共享,可写的数据段就必须各自保留一份了。采用虚拟内存机制后,可以将物理内存中所加载的共享库分别映射到进程各自的地址空间,由于加载地址可能不同,所以共享库必须实现为地址无关码(PIC)。

  第三,VA到PA的映射会给分配和释放内存带来方便,物理地址不连续的几块内存可以映射成虚拟地址连续的一块内存。比如要用malloc分配一块很大的内存空间,虽然有足够多的空闲物理内存,却没有足够大的连续空闲内存,这时就可以分配多个不连续的物理页面而映射到连续的虚拟地址范围。

  第四,“增加”了程序可以使用的内存空间。一个系统如果同时运行着很多进程,为各进程分配的内存之和可能会大于实际可用的物理内存,虚拟内存管理使得这种情况下各进程仍然能够正常运行。因为各进程分配的只不过是虚拟内存的页面,这些页面的数据可以映射到物理页面,也可以临时保存到磁盘上而不占用物理页面。当所访问的页面不在内存中时再将其加载进来,无空闲页面的时候还可能需要采取一定的置换算法将某个页面换出。这种机制的可行性得益于伟大的“局部性原理”。

posted @ 2010-03-09 13:50  Lux  阅读(1056)  评论(0编辑  收藏  举报