文章目录
- 1. 缺页异常的处理流程
- 2.在何处保存未被映射的页?
- 3. 虚拟内存性能
1. 缺页异常的处理流程
缺页中断的处理过程:
-
CPU读内存单元,在TLB中根据其虚拟地址匹配物理地址,未命中,读页表;
-
由于页表项的存在位为0,CPU产生缺页异常;
-
OS 查找到保存在外存中对应的应用的页面内容;
-
如有空闲物理页帧,把外存中的页面内容换入到某空闲物理页帧中;
-
如无空闲物理页帧,通过置换算法释放/换出某物理页帧到外存,再把外存中的页面内容换入到某空闲物理页帧中;
所谓清空需要注意,如果里面的数据被修改过,把这数据还写回硬盘中,如果没有被修改,直接给它释放了,因为和硬盘中对应的那个数据是一样的,没必要再写回,它已经是最新的,这时候把这个页从被使用状态变成空闲状态,再完成从硬盘把相应数据读进来,然后设置页表项,然后再重新执行这一过程。
-
修改页表项,建立虚拟页到物理页帧的映射,存在位置1;
-
OS返回到应用程序,让处理器重新执行产生缺页异常的读内存单元指令。
2.在何处保存未被映射的页?
在这里面,大量内存中的数据是放在外存中,需要才读进来,硬盘存储这些数据的这些特征是什么?需要注意,这里面有好几种不同类型存储形式来放置内存中所对应的数据和代码。
- 数据,比如访问数组,数组是大的数据,可能是数据文件放在硬盘上,当需要访问到某个地方的时候,如果内存没有,那从数据文件中把数据读出来,它是后备存储 (Backing Store)。
- 代码,操作系统让程序在执行过程中,去执行某一条指令,指令其实也是一种数据,这种数据放在硬盘中,硬盘存了很多执行程序。执行程序中代码当作数据读到内存中去,然后让 CPU 去执行这条指令,当访问这条指令不存在的时候,会进一步从执行程序中把数据读到内存中,进一步执行。
- 动态链接库,软件在运行过程中需要库,库其实以库文件形式也是放在硬盘,需要的时候才会把库的代码数据从硬盘读进来。
- 不是以文件形式存在,而是分区形式存在。程序在运行过程中,它有可能产生很多数据,这些数据没有对应到具体的那些文件,无论是数据文件、执行文件,库文件,不是这三种。它就是动态产生的数据,那么这些数据也可能占了很大的空间,且需要被换出到硬盘上去。操作系统会专门在硬盘上开一个区域,叫做swap,换入换出分区。这个区域里面放置这些没有以文件形式直接对应的这些内容。
这四类形成了后备存储,或者二级存储,有二级存储的支持,使得虚存管理可以充分的保证空间的有效性。
3. 虚拟内存性能
通过分页机制和缺页中断处理,使应用程序可以感觉到更大的内存,更快、更便宜,更方便的内存访问空间。这个空间其实是通过缺页异常处理,它可能会涉及跟硬盘读写操作,可能会怀疑虚存管理技术性能怎么样?
上图是一个具体虚存管理性能的公式表达:
EAT = 内存访问时间 * (1-p) + 缺页异常处理时间 * p(1+q)
q = dirty page 几率
比如说内存访问时间可以认为是10 ns;硬盘访问时间是 5 ms;同时设定两个比例,一个是缺页百分比,就是这一段时间之内产生缺页的概率是多大,p 代表缺页的概率, q 代表页写操作概率。有了这几个参数之后,就可以建出一个公式来表达内存的平均访问时间的开销:
EAT = 10(1-p) + 5000000p(1+q)
1- p : 代表没有产生缺页的概率是多大,没有产生缺页的访问时间就是10(1-p);
~
同时如果产生缺页,就是应该是5000000*p,代表产生缺页之后,读操作用时。
~
q :代表对内存页写操作且写操作换出去概率,换出操作也会做一次写硬盘操作,那么这个开销也是5 ms,这里面正常的缺页异常换入操作和dirty page 页的换出操作加起来就是 1+ q。
公式右侧 5000000 >> 10 ,是不是意味着内存访问开销就很大呢,其实它取于另外一个参数 p, p 足够小,就可以使得平均访问时间接近于10 ns,如果 p 比较大,会导致整访问效率会很差。
其实有信心保证 p 足够小,因为程序有局部性特点,意味着它产生缺页的次数会很少。比如说程序在重复访问4K 页,可能访问了100万次才跳出,去访问另一个不在内存中存在的地址,才产生缺页,这时候它的效率就很高。大部分程序从效率来说也是这么设计,使得虚存管理的性能得到保障。