为什么要引入虚拟内存?
扩充逻辑上的内存,使得程序不需要全部,而是部分装入也能运行。
虚拟内存空间由什么因素决定,计算机的地址线数决定。
虚拟内存会解决什么问题,会带来什么问题
解决多道程序中可能存在内存不够的问题。利于多道程序的并发
掌握虚拟内存解决问题的思想,了解几种替换算法的优劣,熟练掌握虚实地址的转换
虚拟内存的基本概念
传统存储方式的特征:
都是把多个进程同时装入内存,以便允许多道程序设计。它们都具有一下两个共同的特征:
一次性:
作业一次性装入内存后,才开始运行。
这样会导致两种情况:1作业很大不能全部装入内存,使得该作业无法运行。2大量作业要求运行,内存不够全部装入容纳所有作业,只能使得少量作业先运行,导致多道程序度的下降。
驻留性:作业被装入内存后,就一直驻留在内存里,其任何部分都不会被换出,直到作业运行结束。运行中的进程会因等待IO而被阻塞,可能处在长期等待的状态
(补充:
- 挂起状态:由于IO的速度慢于CPU的运算速度,经常出现CPU等待I/O的情况。这时OS需要将主存中的进程对换至外存。在进程行为模式中需要增加一个新的挂起(suspend)状态。当内存中所有进程阻塞时,OS可将一进程置为挂起态并交换到外存,再调入另一个进程执行。
)。
局部性原理
时间局部性,刚用过的页面可能不久再用
空间局部性:因为数组向量链表等数据结构的连续性导致集中在一个局部访问
虚拟存储器的定义的特征:
叫这个名字部分因为
系统提供了 装入一部分,请求调入需要的那部分 和满的时候,置换功能 后(用户不可见),导致的结果就是
用户感觉全部的作业都装进了内存。好像有一个比实际的物理内存大得多的存储器。
存储器的大小也是由计算机的地址结构决定,不是内存外存简单相加。
如8根地址线。
决定装入一部分,是根据局部性原理,把常访问的装入内存。其余的留在外存,即可执行程序了。执行的时候访问的信息不在内存的时候,
由操作系统把所需要的部分调进来,接着执行。同时操作系统又把不用的部分调出去,调外存,腾出空间装将要调入内存的信息。
特征(与传统的存储方式对比):
多次:作业没必要一次性装入内存,允许被分成多次调入内存
对换:作业运行时没必要常驻内存,允许作业在运行过程中,进行换进和换出
虚拟:逻辑上扩充内存容量
技术的实现:
可以采用连续分配或者离散分配内存管理方式基础上,但是连续分配导致空间利用率不高,浪费空间,所以采用离散分配。
1请求分页
2请求分段
3请求段页式存储管理
需要操作系统,也需要硬件支持:
1, 一定容量的内存和外存
2, 页表机制作为主要的数据结构
3, 中断机构,如果用户程序访问的部分没调入内存,该机构中断
4, 地址变换机构,逻辑地址到物理地址的变换
请求分页管理方式:
建立在基本分页系统基础上,为了支持虚拟存储器 而增加了请求调页和页面置换功能。请求分页是目前常用的实现虚拟存储器的方法。
具体操作:
页表机制:
和基本分页系统不同的是,
发现和处理 要访问的页面不在内存中这种情况是请求分页系统必须处理的问题
页表项为此增加了四个字段:
状态位:指示该页是否被调入内存,供程序访问时参考。
访问字段:记录本页在一段时间内被访问的次数,置换算法参考
修改位:标识该页调入内存后是否被修改过
外存地址,指出该页在外存的地址,物理块号,供调入该页时参考。
缺页中断机构:
访问的页不在内存时,产生一个缺页中断,请求操作系统把所缺的页调入内存。此时应将缺页的进程阻塞,如果内存里有空闲块,分配一个块把调入的页装入该块,并修改该页表项,若此时没有,需要淘汰某页。
缺页中断作为中断,同样要经历诸如保护cpu环境,分析中断原因,转入缺页中断处理程序,恢复cpu环境等几个步骤
它与一般的中断还有区别:
一条指令执行期间,可能产生多次缺页中断。
指令执行期间而不是执行后产生处理中断信号,属于内部中断。
地址变换机构
这个地址变换机构是在基本分页基础上,为了实现虚拟内存,增加某些功能而形成的。
请求分页的:
地址变换时,先检索快表。
如果找到要访问的页,修改页表项中的访问位(未完)
页面置换算法(选择调入哪页,调出哪页)
好的页面置换算法应该是较低的页面更换频率,不要经常换进换出,导致更换的时间比程序执行的时间都长。
下面是几种页面置换算法:
1最佳置换算法(理想的)
选择淘汰的页面是以后永不使用的页面,然而是无法预先知道哪个是。所以无法实现。
2先进先出页面置换
基于队列实现,不是堆栈类算法。
淘汰最早进入内存的页面,只需要按照先后次序链接成队列,设置成一个指针,总指向最早的页面
3.最近最久未使用算法
认为最近最长一段时间未被访问的页面予以淘汰,它认为过去一段时间内没被访问页面,最近的将来也不会被访问。
该算法为每一个页面设置一个访问字段,来记录页面字上次访问以来的所经历的时间,淘汰页面时选择其中数值最大的予以淘汰。
算法性能比较好,但需要寄存器和栈的硬件支持,是堆栈类算法。理论上证明,堆栈类算法不可能出现belady异常
4时钟置换算法
算法要循环扫描缓冲区。只考虑到是否被访问过,尽可能留下。未访问过的尽可能留下。认为这样可以总体上减少换页次数。
5改进的时钟算法
对使用的页面又做了细分分为使用过但未修改过,和使用过且修改过。如果全部页面都使用过,优先把未修改过的页面换出。
讲完几个算法的大概思路后,讲下页面分配策略
驻留集大小:
操作系统决定读取多少页,也就是给特定的进程分配多少个页框。给一个进程分配的物理页框的集合就是这个进程的驻留集。(页框就是页数)
需要考虑以下几个点:
1分配给一个进程存储量越小,任何时候驻留在主存中的进程数越多,从而可以提高处理机的利用率
2若一个进程在主存页数过少,尽管有局部性原理,页错误率仍然会相对较高。
3页数过多,则根据局部性原理,给特定的进程分配更多的主存空间对该进程的错误率无明显影响。
考虑到这些因素,分配合适的页框数目比较重要。
现代的操作系统有以下三个策略。
1固定分配的局部置换
它给每个进程分配一定数目的物理块,在整个运行期间都不改变。
若干进程在运行期间发生缺页,则只从该进程在内存中的页面中选一个页换出,然后调入重要的页面。
实现这种策略时,难以确定应为每个进程分配的物理块的数目。太少会频繁发生缺页中断,太多,会使得cpu和其他资源利用率下降。
2可变分配的全局置换
这是最容易实现的物理块分配和置换策略。
它为系统中的每个进程分配一定数目的物理块,操作系统自身也保存一个空闲的物理块队列。当某进程发生缺页时,系统从空闲物理块队列中取出一个物理块分配给该进程,并将欲调入的页装入其中。这种方式比固定分配局部置换更加灵活,可以动态增加进程的物理块,但是也有弊端,会盲目增加物理块,导致多道程序并发能力下降。
3可变分配的局部置换
它为每个进程分配一定数目的物理块,当某个进程发生缺页时,只允许从该进程在内存的页面中选取一页换出,因此不会影响其他进程运行若进程在运行中频繁得缺页,此时系统在为该进程分配物理块,直到这个进程的缺页率趋于适当程度。
反之,若进程运行缺页率特别低,可适当减少分配给该进程的物理块。比起可变分配全局置换,这种方法不仅动态增加物理块的数目,还能动态减少,在保证进程不会过多地调页同时,也保持了多道程序的并发能力
什么时候调入页面?
采取以下的调页策略:
预调页策略:按照局部性原理,一次调入相连的页可能比一次调一页更高效。但是调入的一批中大多数都未被访问,也是低效的。因此,需要采用以预测为基础的预调页策略。将预计在不久之后便会被访问的页面预先调入内存。但目前预调页的成功率只有50%,所以这种策略主要用在进程的首次调入。,由程序员指出应先调入哪些页。
请求调页策略
进程在运行中需要访问的页面不在内存而提出请求。由系统将所需要的页面调入内存。在目前的虚拟存储器大多采用此策略。它的缺点是每次只调入一页,调入调出页面数很多时会花费过多的IO开销。
从哪个地方调入页:
请求分页系统的外存分为两部分:用于存放文件的文件区和用于存放对换页面的对换区。对换区通常采用连续分配方式,文件区采用离散分配方式,故对换区的磁盘IO速度会比文件区更快。
存在以下三种情况:
1系统有足够的对换区空间,可以全部从对换区调入所需的页面,提高调页速度。为此,进程隽星前,需要把该进程相关的文件从文件区复制到对换区
2系统没有足够的对换区空间
凡是不会被修改的文件都直接从文件区调入。
当换出这些页面时,因为他们未被修改而不必再把它们换出,但对于那些可能被修改的部分,在将他们换出时换到对换区,以后需要时再从对换区调进来。
3UNIX方式 与进程有关的文件都放在文件区,故未运行过的页面都应该从文件区调入,曾经运行过但又被换出的页面,放在对换区,方便下次调入时应从对换区调入。
进程请求的共享页面若被其他进程调入内存,则没必要从对换区调入
抖动:
页面置换时一种糟糕的情形:刚刚换出的页面又要换入主存,刚刚换入的马上又要换出主存,这种频繁的页面调度行为叫做颠簸。
频繁地发生缺页中断的主要原因是:某个进程频繁访问的页面数目高于可用的物理页帧数目。
虚拟内存技术可在内存中保留更多进程以提高系统效率。
在稳定状态下,几乎主存所有的空间都被进程块占据,处理机和操作系统可以直接地访问到尽可能多的进程。
然而,如果管理不当,处理机的大部分时间都用于请求调页的操作,大大降低系统的效率。
工作集:
指的是在某段时间间隔内,进程要访问的页面集合
一般来说,工作集可由时间t和工作集窗口大小来确定。
比如某个时刻为止的工作集窗口中不重复的页就是工作集大小。