现在的位置: 首页 > 综合 > 正文

一个操作系统的实现03之六3.3

2013年12月11日 ⁄ 综合 ⁄ 共 2065字 ⁄ 字号 评论关闭

页式存储

 

什么叫“页”

所谓页,就是一块内存,386中页大小是4K,pentium的夜可以是2MB或4MB。本书只讨论页为4K的情况。

引入内存分页的目的是为了实现虚拟存储。

虚拟内存(Virtual Memory) 是指计算机呈现出要比实际拥有的内存大得多的内存量。因此它允许程序员编制并运行比实际系统拥有的内存大得多的程序。这使得许多大型项目也能够在具有有限内存资源的系统上实现。一个很恰当的比喻是:你不需要很长的轨道就可以让一列火车从上海开到北京。你只需要足够长的铁轨(比如说3公里)就可以完成这个任务。采取的方法是把后面的铁轨立刻铺到火车的前面,只要你的操作足够快并能满足要求,列车就能象在一条完整的轨道上运行。这也就是虚拟内存管理需要完成的任务。

 

逻辑地址、线性地址、物理地址的关系

物理地址(Physical Address)是指出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址。

逻辑地址(Logical Address)是指由程序产生的与段相关的偏移地址部分,常用Seg:Offset来表示,它是相对于你当前进程数据段的地址。只有在Intel实模式下,逻辑地址才和物理地址相等(因为实模式没有分段或分页机制,Cpu不进行自动地址转换);逻辑也就是在Intel 保护模式下程序执行代码段限长内的偏移地址(假定代码段、数据段如果完全一样)。应用程序员仅需与逻辑地址打交道,而分段和分页机制对您来说是完全透明的。

线性地址(Linear Address)是逻辑地址到物理地址变换之间的中间层。程序代码会产生逻辑地址,或者说是段中的偏移地址,加上相应段的基地址就生成了一个线性地址。

如果启用了分页机制,那么线性地址可以再经变换以产生一个物理地址。

若没有启用分页机制,那么线性地址直接就是物理地址。

图片

 

分页机制概述

图片

如上图所示,线性地址到物理地址的转换使用两级页表。

第1级叫页目录,存储在一个物理页中,每个表项4字节,对应第2级的一个页表。每个页目录有1024个表项。

第2级是页表,每个表项对应一个物理页。每个页表有1024个表项。

另外从图中还可以知道以下信息:

1)页目录是唯一的,它的地址放在CPU的cr3寄存器中,是进行地址转换的开始点。
2)每一个活动的进程,因为都有其独立的对应的虚似内存(页目录也是唯一的),那么它也对应了一个独立的页目录地址。——运行一个进程,需要将它的页目录地址放到cr3寄存器中,将别个的保存下来。
3)每一个32位的线性地址被划分为三部份,面目录索引(10位):页表索引(10位):偏移(12位)

 

线性地址到物理地址转换步骤
1)从cr3中取出进程的页目录地址(操作系统负责在调度进程的时候,把这个地址装入对应寄存器);
2)根据线性地址高十位,在页目录中找到页表的地址;
3)根据线性地址的第12到21位,在页表中找到物理页的起始地址;
4)将页的起始地址与线性地址中低12位相加,得到最终的物理地址;

这个转换过程,应该说还是非常简单地。全部由硬件完成,虽然多了一道手续,但是节约了大量的内存,还是值得的。那么再简单地验证一下:
1)这样的二级模式是否仍能够表示4G的地址;
页目录共有:2^10项,也就是说有这么多个页表
每个目表对应了:2^10页;
每个页中可寻址:2^12个字节;
还是2^32 = 4GB

2)这样的二级模式是否真的节约了空间;
也就是算一下页目录项和页表项共占空间 (2^10 * 4 + 2 ^10 *4) = 8KB。这样正确吗?
按《深入理解计算机系统》中的解释,二级模式空间的节约是从两个方面实现的:
A、如果一级页表中的一个页表条目为空,那么那所指的二级页表就根本不会存在。这表现出一种巨大的潜在节约,因为对于一个典型的程序,4GB虚拟地址空间的大部份都会是未分配的;
B、只有一级页表才需要总是在主存中。虚拟存储器系统可以在需要时创建,并页面调入或调出二级页表,这就减少了主存的压力。只有最经常使用的二级页表才需要缓存在主存中。

值得一提的是,虽然页目录和页表中的项,都是4个字节,32位,但是它们都只用高20位,低12位屏蔽为0——把页表的低12屏蔽为0,是很好理解的,因为这样,它刚好和一个页面大小对应起来,大家都成整数增加。计算起来就方便多了。但是,为什么同时也要把页目录低12位屏蔽掉呢?因为按同样的道理,只要屏蔽其低10位就可以了,不过我想,因为12>10,这样,可以让页目录和页表使用相同的数据结构,方便。

 

CR3

用于保存页目录表页面的物理地址,因此被称为PDBR。由于目录是页对齐的,所以仅高20位有效,低12 位保留供更加高级的处理器使用。向CR3中装入一个新值时,低12位必须为0;但从 CR3中取值时,低12位被忽略。每当用MOV指令重置CR3的值时,会导致分页机制高速缓冲区的内容无效,用此方法,可以在启用分页机制之前,即把PG 位置1之前,预先刷新分页机制的高速缓存。

 

参考文章:http://linux.chinaunix.net/bbs/thread-919019-1-7.html

抱歉!评论已关闭.