本次笔记内容: 5.1 虚拟内存的起因 5.2 覆盖技术 5.3 交换技术 5.4.1 虚存技术(上) 5.4.2 虚存技术(下)
有没有比内存更便宜、容量更大的设备?
有,硬盘。但是硬盘的速度远远慢于内存,程序不能放在硬盘上执行。
因此,操作系统能不能做出一个 更大、更快、更便宜 的虚拟内存空间。程序员直接针对虚拟内存空间操作。
如上图,一种OS抽象技术。在OS Kernel管理下,常用数据代码放在内存中。
在没有虚拟内存技术时,使用覆盖技术或交换技术:
程序太大,超过了内存的容量,可以采用手动的覆盖(overlay)技术;程序太多,超过了内存的容量,可以采用自动交换(swapping)技术。而虚拟内存技术,则是以更小的页粒度为单位,装入更多更大的程序。上世纪80年代,当时操作系统能力较弱(DOS),硬件640K内存。
上图是一个例,A、B、C、D、E、F是六个函数,不存在相互调用关系的函数共享一个内存空间,用到谁时调谁。
注意 ,上例还有另外一种覆盖方法:(100K) A 占一个分区:20K; B、E和F共用一个分区:50K; C和D共用一个分区:30K。
最大问题开销问题非常大:
设计开销大,设计者需要考虑最优设计,如何安排模块;运行过程中不停地涉及到硬盘读写。早期Unix提供的一种方法:当多个程序运行时,交给操作系统管理内存,空间不够时,将不使用的程序导到硬盘中去。
内存保存到外存(swap out)从外存导入内存(swap in)交换技术对于程序员来说是透明的,减轻了程序员的负担,但是系统的开销变大了。
像覆盖技术那样,不是把程序的所有内容都放在内存中,但是是自动执行的,无需程序员干涉;
像交换技术那样,实现进程在内存与外存之间的交换,但是不是以一个程序为粒度,而是以页为粒度。
程序的局部性原理(principle of locality):指程序在执行过程中一个较短时期,所执行的指令地址和指令的操作数地址,分别局限于一定区域。可以表现为:
时间局部性:一条指令的一次执行和下次执行,一个数据的一次访问都集中在一个较短时间内;
空间局部性:当前指令和临近的几条指令,当前访问的数据和邻近的几个数据都集中在一个较小的区域内。
程序的局部性原理表明,从理论上说,虚拟存储技术是能够实现的,而且在实现了以后应该能够取得一个满意的效果的。
例:页面大小为4K,分配给每个进程的物理页面数为1。在一个进程中,定义了如下的二维数组int A[1024][1024],该数组按行存放在内存中,每一行放在一个页面中。
// 程序编写方法1 for (j=0; j<1024; j++){ for (i=0; i<1024; i++){ A[i][j] = 0; } } // 程序编写方法2 for (i=0; i<1024; i++){ for (j=0; j<1024; j++){ A[i][j] = 0; } }https://img-blog.csdnimg.cn/20190917143517404.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjgxNTYwOQ==,size_16,color_FFFFFF,t_70
操作系统只用利用程序的局部性特点,才能很好地实现虚存技术。
大的用户空间:提供给用户的虚拟内存空间通常大于实际的物理内存,即实现了这两者的分离。如32位的虚拟地址理论上可以访问4GB,而可能计算机上仅有256M的物理内存,但硬盘容量大于4GB。
部分交换:与交换技术相比,虚拟存储的调入和调出是对部分虚拟地址空间进行的;
不连续性:物理内存分配的不连续,虚拟地址空间使用的不连续。
物理内存与虚拟内存靠页表进行索引。页表项中,还有代表“存在与否”等的bit。
大部分虚拟存储系统都采用虚拟页式存储管理技术,即在页式存储管理的基础上,增加请求调页和页面置换功能。
基本思路:
当一个用户程序要调入内存运行时,不是将程序的所有页面都装入内存,而是只装入部分的页面,就可启动程序运行;
在运行的过程中,如果发现要运行的程序或要访问数据不在内存,则向系统发出缺页中断请求,系统在处理这个中断时,将外存中相应的页面调入内存,使得该程序能够继续运行。 (请求调页、页面置换)
因此,在页表表项增加几个bit。
例如下。
上图中,X代表驻留位为0。
对于逻辑地址0,其在0K4K,索引值为2,其物理地址为4K*2=8192。而对于32790,32K36K的驻留位为0,因此产生缺页异常。
因此,缺页中断时很重要的一个步骤,导演了内外存相互交换的动作。
具体细节将在实验环节展开讲解。置换算法将在下节课进行讨论。
因此有后备存储的概念:
一个虚拟地址空间的页面可以被映射到一个文件(在二级存储中)中的某个位置;代码段:映射到可执行二进制文件;动态加载的共享库程序段:映射到动态调用的库文件;其他段:可能被映射到交换文件(swap file)为了便于理解分页的开销,使用有效存储器访问时间effective memory access time(EAT)。
EAT = 访问时间 * 页表命中几率 * + page fault处理时间 * page fault几率
例子: 访问时间:10ns 磁盘访问时间:5ms 参数p=page fault几率 参数q=dirty page几率 EAT=10(1−p)+5000000p(1+q) EAT=10(1−p)+5000000p(1+q)
如果p足够小,则使效率够。
我们的程序局部性保证了EAT足够小。
