其中逻辑地址指的是我们熟悉的Segment:Offset模式的地址,在IA-32上,Segment通过Segment Selector来引用一个Segment Descriptor,在Segment Descriptor中定义了Segment Base Address,Segment Limit,以及用作段保护目的的Segment Attribute。在IA-32上任意给出的地址都是一个逻辑地址,即任意一个地址都是通过Segment:Offset的方式给出的。这是段内存访问模式的基本特点。所以我们在IA-32上,我们无法避免使用段模式,因为我们必须按照Segment:Offset的方式给出一个地址。
最终一个逻辑地址会通过Segment Base Address+Offset的方式转化为一个线性地址,线性地址空间是指一段连续的,不分段的,范围为0到4GB的地址空间,一个线性地址就是线性地址空间的一个绝对地址。如果没有页模式,则一个线性地址就被直接映射为物理地址,二者是相同的。
如果使用分页,则可以将一个大的线性地址空间映射到相对小的物理地址空间。其原理就是我们上一节所讨论的页表映射方式。页模式再IA-32上是可选的。
我们在上一节内容中讨论了在内存管理模式中,如果我们想实现有效的虚拟内存管理,以让多个应用程序可以有效的使用有限的物理内存,我们需要使用Paging模式。而Paging模式实现的是线性空间到物理地址空间的映射。而在IA-32上,你无法直接操作线性空间,而只能给出逻辑地址,由IA-32的段机制将其转化为线性地址。但由于绝大多数硬件平台都不支持段模式,而支持Paging模式,所以为了让我们的OS有更好的可移植性,我们需要去掉段模式而只适用Paging模式。
但令人讨厌的是,IA-32规定段模式是不可禁止的,你不可能绕过它直接给出线性空间地址,我们必须使用它。万般无奈之中,我们意识到,如果我们通过设置段,可以访问到全部4 GB线性空间,同时给出的逻辑地址中的Offset恰好等于线性空间地址,那么我们一旦装载好Segment Selector之后,任意时刻给出的地址总是等于被转化后的线性地址的话,那么其效果和直接操作线性空间没有什么不同。
办法就是创建一个基地址为0,Segment Limit为4 GB的段,这时任意给出一个offset,则等式为0+offset=linear Address,也就是说offset=linear Address,另外由于段机制规定offset < 4GB,所以offset的范围为[0h,FFFFFFFFh],恰好是线形空间范围,这一切正是我们想要的。
由于IA-32段机制规定,必须为代码段和数据段创建不同的段,所以我们必须分别为代码段和数据段分别创建一个Base Address为0,Segment Limit为4GB的段描述符,另外,由于我们的OS要让内核运行在特权级0,而用户程序运行在特权级别3,根据IA-32的段保护机制,特权级别3的程序是无法引用特权级别为0的段描述符的(因为CPL>DPL),所以我们必须分别为内核和用户程序分别创建其代码段和数据段。这就意味着我们必须创建4个段描述符——特权级别0的代码段,特权级别0的数据段,特权级别3的代码段,特权级别3的数据段。
如果我们这么定义段,段保护则失去了作用,因为这些段使用完全相同的线形空间,它们互相覆盖。你可以设想,如果不使用Paging的话,线形空间直接被影射到物理空间,则你修改任何一个段的数据,都会同时修改其它段的数据,段机制所提供的通过Base Address:Limit方式将线形空间分割,以让段与段之间完全隔离,来实现段保护的方式在这种情况下根本就不存在了。那么这是不是意味着用户可以随意修改内核数据了?不要慌,我们之所以这么定义段,正是为了实现一个纯的Paging,此时我们已经不需要任何来自于段的保护(如果它提供了对我们来讲反而可能是个负担,比如我们仍然不得不使用4个段描述符。对一个纯粹的Paging而言,段机制的任何痕迹都是多余的),而Paging机制会提供给你所有你所需要的保护。
2. Page Table
IA-32模式对应两种页大小,提供了2种页表模式。对于4 KB页,使用2级页表;而4 MB则使用1级页表。我们不讨论4 MB的页,只讨论4 KB的页表模式。
4KB页的2级页表模式与我们在上一节讨论的相同,这里就不再赘述。我们下面来看一看Page-Directory Entry和Page-Table Entry的格式。
如果CPU产生一个Page-Fault异常,OS Kernel中的Page-Fault异常处理程序必须按顺序做如下处理:
Present位是实现请求页虚拟内存算法的关键位,所有支持Paging的硬件平台都肯定支持这个位。
Read/Write域是页保护机制的关键位之一,所有支持Paging的硬件平台都肯定支持这个位。
User/Supervisor位是页保护机制的关键位之一,所有支持Paging的硬件平台都肯定支持这个位。
3. Enable Paging