Linux下地址映射原理

一、Intel x86芯片发展过程
      在x86体系中,8086及以前是16位处理机,80386是32位处理机,80286是16位到32位的过渡芯片。这里CPU的位数是指“算术逻辑单元ALU”的宽度,也指数据总线的条数。通常数据总线的条数与地址总线的条数保持一致,但8位CPU的寻址能力仅仅能够寻访256个地址单元,这显然是不够的,因此,8位CPU地址总线的宽度设计为16位,即地址空间为64K。但之后的使用中,64K已经无法满足人们的操作,Intel决定加到1M,即地址总线宽度调整为20位,这就是8086所采用的设计结构:16位CPU,20位地址总线宽度。
   同时,产生了一个新的问题?地址总线与数据总线不对等。


二、实地址模式下的地址映射

   Intel在8086中设置了4个寄存器:CS(代码段寄存器)DS(数据段寄存器)SS(堆栈段寄存器)ES(扩展段寄存器)。每个段寄存器都是16位,对应每个段的起始地址的高16位。这是由于物理地址被划分成一段一段的,每个内存段都是16的整数倍,即在20位的地址中,低四位全为0,没有必要存储。
   因此,实模式下地址映射表达式为:(假如寻找数据地址)
                          DS<<4 + IP = 数据地址
   DS<<4得到真实的20位段基地址,加上IP寄存器存放的偏移量,即逻辑地址,就可以找到数据所存放的位置,这里的数据地址为物理地址。因此,在实模式下,可以直接通过修改段寄存器的内容访问内存中的任何一个地址单元,不受任何权限控制,没有保护措施。


三、保护模式下的地址映射

   以80386的32位CPU为讨论对象,由于Intel 80386芯片要兼容以前设计,保留以前16位的段寄存器,同时又增添了两个新的寄存器:FS和GS。设计的基本思路:设计一个数据结构,包含基地址,地址段长度及访问权限等信息,在保护模式下需要改变段寄存器的功能,把原来存放段基址的功能改变成存放一个数据结构的指针。
    基本过程:
        (1)根据指令的性质判断使用哪一个段寄存器;
        (2)在段寄存器中找到相应的数据结构;
        (3)在此数据结构中找到段基地址;
        (4)根据指令地址(偏移量)和地址段大小比较,判断是否越界;
        (5)根据指令权限与数据结构中的权限对比,判断是否越权;
        (6)段基址+指令地址得到物理地址。
    实现过程:80386CPU中又增加了两个寄存器:GDTR(global descriptor table register)全局的段描述表寄存器LDTR(local descriptor table register)局部的段描述表寄存器
    段寄存器如图所示:
    段寄存器的高13位包含了8192个全局或局部的段描述表项描述符,它与GDTR或LDTR的基地址相加才得到描述表项的起始地址。每个段描述表项为8字节,存放段基址,段大小和其他信息,具体结构如图所示:
起始地址32位:B31-B24,B23-B16,B15-B0
长度20位:L19-L16,L15-L0
长度单位G,为0代表单位为字节,为1时代表页面
  因此,保护模式下的地址映射表示为:
                     GDTR[DS>>3].BaseAddr + IP  = 线性地址

  DS>>3取得GDTR表项的下标,GDTR[DS>>3].BaseAddr找到该表项的基地址,再加上逻辑地址,得到该数据的线性地址。此处不为物理地址是还要进行内存分页机制。


  当一个段寄存器的内容改变时,CPU根据段寄存器找到对应的段描述表项,将新的表项装入CPU中。此过程中会检查描述表项的p标志位,为0代表描述表项所指向的内容不再内存中(在磁盘某个地方),此时会产生异常,相应程序会从磁盘交换区将此内容读入内存,并设置基地址,在把p置为1.
  由于保护模式下对内存操作具有权限控制,使得用户不能随意改变GDTR或LDTR的值,所以具有保护机制。


四、内存分页机制

   80386不仅实现了对段式内存管理,还实现了对页式内存管理。在段式内存管理中,连续的逻辑地址映射到物理地址也是连续的,但在页式内存管理中,连续的逻辑地址映射到物理地址不是连续的。

   页式内存管理中,CR3寄存器存放页目录的起始地址,原来的线性地址有了新的定义,高10位为页目录,次高10位为页表,低12位为页内偏移offset。


   页目录中有2^10=1024项,页表也有2^10=1024项,页内偏移2^12=4K,每个页目录项指向一个对应的页表,每个页表指向对应的偏移量所以整个页面映射可以映射到4G的虚拟地址空间。
   内存分页映射过程:
    (1)从CR3寄存器中找到页目录的起始地址;
    (2)页目录起始地址在加上页目录项存放的偏移量得到页表的起始地址;
    (3)页表的起始地址加上页表项的偏移量得到物理地址的基地址;
    (4)物理地址的基地址加上页内偏移最终得到真实的物理地址。
   由于每个页面都是4K,页面基地址都是4K的整数倍,所以页目录和页表对应的描述项只存放地址高20位,低12位可存放其他权限等信息。如最低位present位,为0时代表此页面不在内存中。


   总结:(以数据地址为例)通过数据段寄存器<<3位得到全局段描述表的下标,找到对应的描述项,即得到32位的基地址,再加上IP寄存器里的偏移量得到线性地址。通过寄存器CR0判断是否开启内存分页机制,没有开启时,则此时的线性地址就为物理地址,如果开启了内存分页,则通过多级页表映射找到对应的物理地址。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值