随着时间的推移,程序不断地更新,规模不断增长,运行的时候可能会发现内存会越来越不够用。所以希望一个容量大,更快,更便宜,数据不易丢失的存储器。
首先想到的就是硬盘,所以在硬盘的基础上建立了覆盖技术,把常用的数据放在内存,不常用的数据放在外存。或者使用交换技术,把最近使用的数据放在内存,把很久没用的内存数据换到外存。现如今,我们在分页分段的基础上建立了虚拟内存技术。
一、覆盖技术
典型的案例是DOS操作系统:
程序需要按照自身的逻辑划分出多个功能上独立的模块把那些不会同时运行的模块共享同一个内存空间(分区),按照时间的先后来执行。这需要一个常驻内存的代码空间,它主要负责管理在某个时间段把哪些数据,函数导入/导出内存。对于不常用的功能,在其他程序执行的时候需要把这功能上的数据放到外存中去,需要的时候再装入内存。
此覆盖技术的缺点就是需要程序员自己去实现各个模块之间的覆盖关系,大大增加了编程难度。另外,模块用调用时间来换取内存空间的节约。其程序的运行时间效率会大大降低。
二、交换技术
典型案例 Unix 操作系统。
考虑由操作系统来帮助程序员完成数据的导入/导出操作。在CPU 和 MMU (内存管理单元)的帮助下,在某个时刻将整个程序的空间导出到外存中。在需要的访问的时候,再把整个程序空间导入到内存中。此技术需要考虑的问题是:
1)什么时候开始交换?
当内存不够用或者内存有不够用的风险时才考虑换出。内存读写和硬盘读写效率相差甚大,可能内存需要在次读程序时还要等硬盘写完才能够换入
2)交换区的大小应为多大合适?
3)程序换入时的重定位
当需要换入的时候,分配到的内存空间可能会不一样,那么程序运行时寻址的问题就需要考虑了?可以考虑页表的动态地址映射。
三、虚拟内存技术
像覆盖技术那样,虚存技术并不会把所有程序都搬到内存中,因而可以运行比空闲内存还要大的程序。但这个分配部分程序的实现不再由程序员完成,而是由操作系统和MMU完成。也像交换技术一样,在某些情况可以以更小的粒度(页)为单位实现内存与外存的交换。
程序的局部性原理:分为时间局部性和空间局部性。所谓时间局部性就是一条指令的一次执行和下次执行,一个数据的一次访问和下次访问都集中在很短的时间内。所谓的空间局部性当前指令的和邻近的指令,当前访问数据的邻近的数据访问,其内存地址都集中在很小的空间中。
虚拟页式内存管理:当用户程序需要把数据调入内存中时,只把部分指令的数据装进内存中。如果正常执行指令的时候发现,数据不在内存中,则会抛出缺页/缺段中断给操作系统请求调页。之后,由操作系统把外存的数据按页搬进内存中,如果程序内存的可用空间不足,那么操作系统会考虑(页面置换算法)把哪些内存数据换出到外存,腾出内存空间。
虚拟内存有大用户空间、部分交换、不连续性的特征。把物理内存和外存相结合,使执行用户程序可以比内存大,换入/换出操作使得程序虚拟内存的分配可能不连续,但是寻址由操作系统完成。
有效存储器访问时间(EAT,Effective Memory Access Time ) =访问内存时间 * 页表命中几率 + 缺页处理时间 * 页表非命中几率。
dirty page :脏页,正在写磁盘或者等待写磁盘的页
page fault : 缺页异常, 当访问内存时,找不到数据对应的页。