一、虚拟内存
(1)每个程序拥有自己的地址空间,被分割成多个块,每一块称为一页。
(2)这些页被映射到物理内存,但不要求所有页都要映射,也不要求映射到连续的物理内存。
(3)当程序引用到不在物理内存中的地址空间时,马上映射到物理内存,然后重新执行指令。
二、分页与分段
1. 分页
虚拟地址空间划分成等长固定大小的页,在物理内存中对应的单元称为页框。
页和页框大小通常相同,它们之间通过页表进行映射。
程序最开始只将一部分页调入页框中,当程序引用到没有在页框的页时,产生缺页中断,进行页面置换,按一定的原则将一部分页框换出,并将页调入。
2. 分段
分页方式的缺点是页长与程序的逻辑大小不相关。
分段:
段长可变,例如 int 类型对象,char 类型对象就可以划分到不同的段。
虚拟地址到内存地址的变换通过段表来映射,虚拟地址由段号和段内地址组成。
缺点: 容易在段间留下许多碎片,造成存储空间利用率降低。
3. 段页式
(1)用分段来分配和管理虚拟内存
程序的地址空间按逻辑单位分成基本独立的段,而每一段有自己的段名。
然后把每段分成若干页。
(2)用分页来分配和管理物理内存
把整个内存分成与上述页大小相等的存储块,可装入作业的任何一页。
(3)程序对内存的调入或调出是按页进行的,但它又可按段实现共享和保护。
(4)举个栗子。
程序员想创建两个对象,一个是 int 型(4 字节),另一个是 char 型(1 字节)。于是他使用这样的语句char s; int a;
,对程序员来说,这是分段,大小由自己指定。而对于计算机内存来说,由于 char 类型对象占的内存更小,则必须把内存分成一个个都是 1 字节的页,这是分页,大小固定。然后把 s 放入一页,再把 a 放入四页。
三、分页系统地址映射
- MMU:内存管理单元,管理虚拟地址空间到物理内存的映射。
- 页表:Page Table,页到页框的映射。(页是虚拟地址空间的概念,页框是物理内存的概念)。
图中 Page Table 分为三部分,拿第 0 个表项(0-010-1)为例。
最左边的 0 表示页面号(虚拟地址空间概念),中间的 010 表示页框号,即第 2 个页框(物理内存概念),最右边的 1 表示页已经放入内存。图中有 16 条表项,需要用 4 个比特位来进行索引定位。
因此对于虚拟地址(0010-000000000100),前 4 位是用来存储页面号,而后 12 位存储在页中的偏移量。(0010-000000000100)根据前 4 位得到页号为 2,读取表项内容为(110-1)。
它的前 3 为为页框号,最后 1 位表示该页在内存中。最后映射得到物理内存地址为(110 000000000100)。所以对于一个虚拟地址,把前面要索引定号的 n 位换成页表中的对应页框就转换好了。
四、页面置换算法
在程序运行过程中,如果要访问的页面不在内存中,就发生缺页中断从而将该页调入内存中。
此时如果内存已无空闲空间,系统必须从内存中调出页面到磁盘对换区中来腾出空间。
页面置换算法的主要目标是使页面置换频率最低(缺页率最低)。
1. 最佳(Optimal)
所选择的被换出的页面将是最长时间内不再被访问,通常可以保证获得最低的缺页率。
是一种理论上的算法,因为无法知道一个页面多长时间不再被访问。
举例:一个系统为某进程分配了三个物理块,并有如下页面引用序列:1234321
开始运行时,先将 1、2、3 三个页面装入内存。
当进程要访问页面 4 时,产生缺页中断。
这时会将页面 1 换出,因为页面 1 再次被访问的时间最长。
2. 先进先出(FIFO)
会将经常被访问的页面也被换出,导致缺页率升高。
3. 最近最久未使用(LRU)
Least Recently Used
虽然无法知道将来要使用的页面情况,但是可以知道过去使用页面的情况。
可以用栈来实现该算法,栈中存储页面的页面号。当进程访问一个页面时,将该页面的页面号从栈移除,并将它压入栈顶。这样,最近被访问的页面总是在栈顶,而最近最久未使用的页面总是在栈底。
4. 时钟(Clock)
我不懂!原文如下:
需要用到一个访问位,当一个页面被访问时,将访问位置为 1。
首先,将内存中的所有页面链接成一个循环队列,当缺页中断发生时,检查当前指针所指向页面的访问位,如果访问位为 0,就将该页面换出;否则将该页的访问位设置为 0,给该页面第二次的机会,移动指针继续检查。