IA之32位体系下Linux系统下虚拟地址空间映射(上)

(一)inter X86体系发展

(1)在8080-8085这两种体系中,CPU位数均为8位,也就意味着ALU(算术逻辑单元)一次能够计算的整数的最大字节数为1byte,即ALU的宽度为8位,数据总线的条数为8条;地址总线的条数为16条,可寻址能力为2^16=64k,;

(2)在8086又开始了一个新的体系,CPU位数为16位;从80386之后CPU位数就真正开始为32位,地址总线为20条。

(二)实地址模式

由于要遵守向上兼容的特性,但是地址总线20条,这使得16位不够表示20位地址,所以引入了4个寄存器来完成保存呢地址的任务;这四个寄存器分别是CS(代码段寄存器) DS(数据段寄存器) SS(堆栈段寄存器) ES(可扩展段寄存器) ,另外还有一个记录偏移量的IP寄存器,这些寄存器大小都为2byte。那么如何利用这些寄存器存储地址呢?

当下的体系将物理内存分为很多段,必须保证每个段的起始地址都是16的倍数,所以每个段大小的区间在16~2^16(64k)(IP寄存器总共16位,将其填满),上述四个寄存器分别存放对应内容的段起始地址,IP寄存器存放要访问的内容距离起始地址对的偏移量,并且由于能被16整除的数字第四位全为0,我们可以利用这个特性只在寄存器中存放高16位,这样比如现在我们要访问在数据段的某个数据,则有DS<<4 + IP =数据的地址 ( 物理地址)。如图所示:

从上图可以看出我们可以直接访问到物理地址,这种直接访问物理地址的访问方式称为“实地址访问或者实地址模式”。这个阶段并不存在操作系统。在这种模式下并不安全,没有权限设置,我们可以修改任意寄存器的值来访问不同的段,修改不同段的内容,

(三)保护模式

   保护模式下的地址映射主要考虑到了我们在访问内存时需要注意的边界条件,通过这些边界条件的控制更好的使用内存空间,这些边界条件主要有:内存的起始地址、内存的大小以及内存的访问权限。那么对于我们所划分的每一个内存段来说,都需要存储这三个边界条件信息,在此又引入了两个寄存器:GDTR(全局的段描述符表)、LDTR(局部的段描述符表),现在内核已经不再使用LDTR,所以在这里只详细介绍GDTR;

GDTR寄存器中保存的是GDT(全局的段描述符表)的地址,由此可以找到GDT,这个GDT我们可以看成是一个数组,每个格子里保存了上述的三个边界条件:内存的起始地址、内存的大小、内存的访问权限,我们将每个格子称作一个段描述符表项,其结构如下图所示:

 

上图中表示的是GDT表布局和其中一个段描述符表象的布局,GDT的每一个格子存储三个边界条件,那么他们具体的布局就如上图所示,下一个问题就是如何访问GDT的每个格子呢,这就用到了我们在实模式下直接用来保存段基址的寄存器,不同的寄存器保存对应内容的GDT表的下标,下面以DS寄存器(16位)为例讲解如何存储下标:

那么我们来梳理一下保护模式下的地址访问:

(1)首先确定访问的数据的类型,通过DS/CS/SS/ES四个寄存器中的一个查找自己所有访问GDT下标;

(2)通过GDTR寄存器找到GDT表的起始地址;找到自己所要访问的内存段,即GDT[(DS>>3)]、GDT[(CS>>3)]、GDT[(SS>>3)]、GDT[(ES>>3)]---------》BASE_ADDR,找到段基址;

(3)将IP地址的偏移量与Length比较,如果在合理范围内,则有GDT[(DS>>3)] + IP = 线性地址;

(4)混淆点:保护模式下的地址访问完成了逻辑地址到线性地址的转换,在此时检查内核是否开启分页机制,如果没有开启分页机制,那么此时的线性地址就是物理地址;如果开启了分页机制,那么此时的线性地址也是虚拟地址,必须经过多级页表映射才能找到其物理地址;下图为这一过程的主要流程:

 

本次讲解就到这里了

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值