当出现内存不够用的情况,该怎么办?
- 如果程序太大,超过了空闲内存的容量,没有办法把它全部装入到内存中,在这种情况下,可以采用覆盖技术。只把当前需要的指令和数据保存在内存中,而把其他的指令和数据保存在外存中。
- 如果程序的个数太多,它们的总和超过了内存的容量,从而使新的进程无法运行,在这种情况下,可以采用交换技术,把暂时不能执行的程序送到外存中。
- 如果想要在有限容量的内存中装入尽可能多的程序,而且每一个程序又要尽可能大,在这种情况下,可以采用虚拟存储技术。
5、覆盖技术
引入覆盖技术的目的是想在较小的可用内存中运行较大的程序。它常用于多道程序系统,与分区存储管理配合使用。
基本原理
:把程序按照自身的逻辑结构,划分为若干个功能上相对独立的程序模块,那些不会同时执行的模块共享同一块内存区域,并且按照时间的先后顺序来运行。
- 将程序的必要部分,即常用功能的代码和数据常驻内存。
- 将程序的可选部分,即不常用的功能,放在其他的程序模块中。平时存放在外存中,在需要的时候才把它装入到内存。
- 对于那些不存在相互调用关系的模块,可以存放在同一个内存分区。当需要一个模块的时候就把它将之前的模块覆盖掉。
缺点:
- 需要程序员确定程序的模块关系。
- 覆盖模块从外存装入到内存,是以时间的延长来换取空间的节省。
6、交换技术
如果有多个进程在并发运行时,那么可以将一些暂时不能运行的进程送到外存当中,从而把它占用的内存空间空出来,用来装入新的进程,或者是读入保存在外存中而且处于就绪状态的进程。
基本原理:把一个进程的整个地址空间保存到外存的一个交换区中,这个过程是换出;然后再将外存中的某个进程的地址空间读入到外存中,这个过程是换入。
总结:
- 覆盖只能发生在那些相互之间没有调用关系的程序模块之间,因此用户必须给出程序内各个模块之间的逻辑覆盖结构。
- 交换是以进程为单位来进行的,它不需要用户给出各个模块之间的逻辑覆盖结构。
- 交换发生在进程之间,覆盖则是发生在同一个进程的内部。
7、虚拟存储技术
虚拟存储技术的目标?
- 像覆盖技术那样,不是把程序的所有内容都放在内存中,而是把一部分正在使用的内容放在内存中。这个过程由操作系统完成。
- 像交换技术那样,能够实现进程在内存与外存之间的交换,从而获得更多的空闲内存空间。但是还想做的更好,也就是只是对进程的一部分内容在内存和外存之间进行交换,而不是把进程的整个地址空间都换出换进。
程序的局部性原理可以保证上面的目标实现。
程序的局部性原理:在一个程序的运行过程中,在某一段时间内,这个程序只有一小部分内容处于活跃的状态,而其它大部分内容可能都处于一种休眠的状态,没有被使用。
在很多地方都用到了程序的局部性原理,比如 :页式地址映射中的TLB(快速查找硬件),CPU中断的高速缓存Cache,它们都是基于局部性原理的。
- 虚拟存储技术的原理
基本原理:在装入程序时,不必把整个程序都装入到内存中,而只要将当前需要执行的那部分页面或段装入到内存中,就可以让程序开始执行。这程序的执行过程中,如果发现需要执行的指令或者是数据不在内存中,就称为缺页或缺段,这时就要产生一个硬件中断,CPU会通知操作系统将相应的页面或段调入到内存中。另一方面,操作系统会将内存中暂时不实用的页面或段暂时调出去,保存在外存中,从而腾出空间。
7.1虚拟页式存储管理(主流的存储管理技术,如Windows和Linux都是采用这种技术)
虚拟页式存储管理就是在页式存储管理的基础上,增加了请求调页和页面置换的功能。
基本思路:当一个用户程序要调入内存运行时,不是将该程序的所有页面都装入到内存,而是只装入部分页面,然后就可以启动该程序执行。在运行的过程中,如果发现要执行的指令或数据不在内存中,就向操作系统发出缺页中断请求,然后系统在处理这个中断的时候就会将保存在外存中的相应的页面调入到内存中。
在具体实现虚拟页式存储管理时,要解决几个问题:
- 如何发现执行的程序或访问的数据不在内存?
- 程序或数据什么时候调入内存,采用何种调入策略?
- 当一些页面调入内存,且内存中没有空闲的空间时,将淘汰哪些页面,即采用何种淘汰策略?
①页表选项
在之前的页式存储管理中,对于每一个进程,操作系统都会为它维护一张页表,对于每一个页表项包括两个信息:逻辑页面号和相应的物理页面号。
但是在虚拟页式存储管理中,还包括
驻留位,保护位,修改位和访问位等等
逻辑页面号 | 访问位 | 修改位 | 保护位 | 驻留位 | 物理页面号 |
- 驻留位:如果驻留位的值为1,表示该页面现在位于内存中,也就是说这个页面是有效的。如果驻留位的值为0,表示该页面现在还处于外存中,也就是说这个页面是无效的;如果此时访问该页面,则MMU会自动发出缺页中断。当CPU访问内存单元的时候,是由MMU进行地址映射,在地址映射时,会去内存或TLB中读取相应的页表项。
- 保护位:表示允许对该页面进行何种类型的访问,如:只读,可读写,可执行等。例如:代码段的页面一般是只读和可执行,数据段、堆和栈的页面一般是可读,可写的。
- 修改位:表示该页面在内存中是否已经被修改过。如果该页面的内容被修改过,CPU会自动将这个位设置为1。因为进程运行时只是将部分页面保存在内存中,当需要读入其它的页面时,需要把内存中页面重新保存到磁盘中;如果发现修改位为1,则表示该页面修改过,必须将该页面保存到磁盘中。如果发现修改位为0,表示该页面没有被修改过和磁盘上的内容一样,这时就不用再保存到磁盘中,直接可以覆盖该页面。
- 访问位:表示该页面在内存中曾经被访问过,不管是读或者是写,只要被访问过,这一位的值就会被硬件自动设置为1。这个信息主要用在页面置换算法中。
②缺页中断
在地址映射过程中,如果要访问的逻辑页面p不在内存中,则产生缺页中断。中断的处理过程如下:
- 如果在内存中有空闲的物理页面,则分配一页,设其编号为f,转去执行第四步,否则转去第二步
- 若内存已满,则采用某种页面置换算法,选择一个将被替换的物理页面f,它对应的逻辑页面为p‘,然后把它从内存中替换出去。(要根据修改位决定是保存到磁盘还是直接覆盖它)
- 对p'所对应的页表项进行修改,将驻留位设为0,表示这个页面已经不在内存中了。
- 将需要访问的逻辑页面p装入到物理页面f中,这就需要去访问磁盘。但是在访问磁盘的时候,这个进程就会被堵塞起来,然后系统去调用另一个进程去执行。当I/O操作完成之后,会有一个I/O中断,使得原来的进程变为就绪状态。当它重新开始运行后,会修改p所对应的页表项的内容,把驻留位设为1,把物理页面号设为f。
- 重新运行被中断的指令,此时它需要访问的页面p已经在内存中了,就可以顺利的运行了。
7.2页面置换算法
最简单的方法是随机法,从内存中随机地选择一个页面,把它置换出去,但是很明显这不是一个好方法。
我们应该将那些未来不再使用的,或是短期内较少使用的页面换出去,而把那些经常要访问的页面保留下来。
主要算法:最优页面置换算法,最近最久未使用算法,最不常用算法,先进先出算法,时钟页面置换算法。
- 最优页面置换算法(Optimal,OPT)的基本思路是:当一个缺页中断发生时,对于保存在内存中的每一个逻辑页面,计算在它的下一次访问之前,还需要等待多长时间,然后从中选择等待时间最长的那个,作为被置换的页面。但是我们根本不知道每一个页面还要等多长时间才再次被执行。
- 最近最久未使用算法(Least Reently Used,LRU)的基本思路是:当一个缺页中断发生时,从内存中选择在最近一段时间内最久没有被使用的那个页面,把它淘汰出局。
在具体的实现上,LRU算法需要记录各个页面使用时间的先后顺序,因此系统的开销比较大。
三种实现方法:系统维护一个页面链表,系统设置一个活动页面栈,给相应的页面打上时间戳。
- 最不常用算法(Least Frequently Used ,LFU)的基本思路是:当一个缺页中断发生时,选择访问次数最少的那个页面,把它淘汰出去。
在具体实现上,对每一个页面设置一个访问计数器,每访问一次就将这个页面的访问计数器加1。
- 先进先出算法(First-In First-Out, FIFO)的基本思路是:选择在内存中驻留时间最长的页面,把它淘汰出去。
在具体实现上,系统维护一个链表,在这个链表上,记录了所有位于内存中的逻辑页面。从链表的顺序来看,链首页面的驻留时间最长,链尾页面的驻留时间最短。也可以用队列来实现FIFO。
Belady现象:采用先进先出算法,有时候会出现分配的物理页面数增加,而缺页率反而提高的异常现象。(原因:置换算法的目标是替换出那些将来较少使用的页面,但是先进先出算法替换的是驻留时间长的页面,因此被这种算法置换出去的页面不一定是系统不会访问的页面)
- 时钟页面置换算法(Clock)的基本思路是:①需要用到页表项中的访问位。当被访问时,硬件自动设置为1,需要系统定期的清0②把各个页面组织成环形链表的形式,类似于一个钟的表面,然后把指针指向最古老的那个页面,即最先进来的页面。③当发生缺页中断的时候,如果最古老的那个页面的访问位是0,就说明该页面的驻留时间最长,并且近期没有被访问过,因此将它淘汰。如果访问位为1,则将其清0,并且考虑下一个页面。
7.2工作集模型
驻留集是指,在当前时刻,进程实际驻留在内存当中的页面集合。驻留集取决于系统分配给进程的物理页面的个数和采用的页面置换算法。
7.3虚拟页式的设计问题
①页面的分配策略
页面的分配策略指的是,对于每一个进程,应该给它分配多少个物理页面,如何确定其驻留集的大小。主要有两种策略:固定分配策略和可变分配策略
固定分配策略:驻留集是固定不变的。
可变分配策略:驻留集的大小是可变的。
缺页率:就是缺页的次数与内存访问次数之间的比率。影响缺页率的因素:
- 页面置换算法的选择
- 分配给进程的物理页面数目
- 页面本身的大小
- 程序的编制方法
缺页率算法的基本思路是,通过对进程当前的缺页率的分析,来动态地调整它所占用的物理页面数。(对于进程的缺页率设置了一个下边界和一个上边界)
②页面的大小
在现在操作系统中(Linux和Windows),页面的大小一般都是4KB。
- 页面越小,内碎片就越小
- 页面越小,需要的页表项就越多,页表就会越庞大,占用的内存空间就越多。
- 页面越小,传送相同大小的内容,需要传送的次数就越多。
- 页面太大,则里面有些东西暂时用不到,浪费内存空间。
③页表结构
页表的功能是将逻辑页面号映射为物理页面号。现在计算机使用的虚拟地址至少是32位,因此虚拟地址空间的大小为2^32 = 4GB。如果每个页面为4KB,那么逻辑页面的个数为2^20,也就是说有2^20个页表项。如果每个页表项的大小为4B,那么总的大小为4MB。这仅仅是一个进程。事实上,系统中的每个进程都有自己的虚拟地址空间,都需要自己的页表,这会占用大量的内存。因此提出了两种结构,多级页表和反置页表。
- 多级页表的基本思路是:虽然进程的逻辑地址空间很大,但是在进程运行时,并不会用到所有的虚拟地址,因此没有必要把所有的页表项都保存在内存中。
- 反置页表
7.2虚拟段式存储管理
7.3虚拟段页式存储管理
知道就有就行