寻址方式

Intel X86 CPU 系列的寻址方式:

处理器:8086、8088、80186、80286、80386、80486 以及后面的各种型号的Pentium芯片。

8086和8088 是16 位(算术逻辑单元)处理器,从80386开始为32位处理器。80286仍为16位处理器,但其寻址方式开始从“实地址模式”到“保护模式”过渡。

8086

是16位CPU,1M(2^20)字节内存地址(20位的地址总线)。8086CPU中设置四个“段寄存器”:CS可执行代码及指令、DS数据、SS堆栈、ES其他。

 

对于每一个段寄存器的内容确定的“基地址”,一个进程总是能够访问从此开始64K(2^16)字节的连续空间。也就是说,可以通过修改段寄存器的内容,一个进程可以随心所欲访问内存中任意的地址。

由于8086内存寻址方式缺乏对内存的保护(“实地址模式”),所以引入了“保护地址模式”。

80286作为过渡,开始实现“保护模式”(早期的80286只能从实地址到保护地址)。

80386(段式内存管理)

80386CPU中增添两个寄存器:全局的段描述表寄存器GDTR、局部性的段描述表寄存器LDTR,用来存放一个指向存储在内存中段描述结构的数组指针(段描述表)(为了实现“保护模式”并且兼容之前的处理器,而设计的结构。其指向的结构有段的基地址段大小一些其他信息。把原来段寄存器的内容(单纯的基地址)变为一个数组指针)。

段描述结构存储在内存,在实际使用时将其装载入CPU中的一组“影子”结构(CPU复制一份),而在运行时则使用其在CPU中的“影子”。

逻辑地址转换成物理地址时,对其权限进行检查,若是高权限(内核权限,RPL为00)才允许访问“影子”描述符。

在增添了两寄存器(全局的段描述表寄存器GDTR、局部性的段描述表寄存器LDTR,存放段描述结构的数组指针)此基础上,原来的段寄存器(CS可执行代码及指令、DS数据、SS堆栈、ES其他)的高13位用作段描述表中具体描述结构的下标。

 

 

将段寄存器内容的低3位屏蔽掉之后与GDTR或LDTR中的基地址相加得到描述表项(包含有段的基地址、段大小和一些其他信息)的起始地址。

 

 

结构体大小为64位(8个字节)。

为什么段描述项这么奇怪?最合理的解释是Intel起先意图设计24位地址空间,后来又认识到应为为32位地址空间。

可以从段长度字段拆为两节可以印证:当G标记为1时,长度单位为4KB。而段长度字段的低16位的容量是64K(2^16),所以一个段的最大可能长度为64K * 4K = 265M,而正是24位地址空间的大小。

段式内存管理只是i386保护模式(系统状态、用户状态和特权指令)的一部分,GDTR和LDTR的内容只能由特权指令在系统状态(内核操作)下修改,进而用户程序不能改变GDTR和LDTR的内容,也无法知道其段表在内存的位置,从而无法通过修改段表来打破系统的保护机制。

“段”是可变长度的,使得盘区交换操作不方便;“段”分得多了,频繁修改段寄存器的内容;8192个段表也不够用。

保护模式的实现是与段式存储分不开的(一些权限在段表中),所以页式管理系统利用已经存在的资源。段式管理将逻辑地址映射出线性地址,然后再由页式管理将线性地址映射成物理地址。当不使用页式管理时,就将线性地址直接用作物理地址。

页式管理把线性地址空间划分成4K字节的页面,每个页面可以被映射至物理存储空间中任意4K字节大小的区间(边界必须与4K字节对齐)。

 

 

对32位线性地址的新解释:

 

页目录中共有2^10 = 1024个目录项,每个目录项指向一个页面表,而在每个页面表中又有1024个页面描述项。类似GDTR和LDTR,又增加了一个新的寄存器CR3作为指向当前页面目录的指针。

从线性地址到物理地址的映射过程为:

 

  1. 从CR3取得页面目录的基地址。
  2. 以线性地址中的dir位段为下标,在目录中取得相应页表的基地址。
  3. 以线性地址中的page位段为下标,在所得到的页面表中取得相应的页面描述项的基地址。
  4. 将页面描述项中给出的页面基地址与线性地址中的offset位段相加的到物理地址。

 

对于64位的CPU:

Linux内核映射机制为三层在页目录和页面表中间增设了一层“中检目录”。

 

 

 

  1. 用线性地址中最高的一位位段(10位)作为下标在页目录PGD中找到指向中间目录PMD;
  2. 用线性地址中第二位为下标找到在中间目录PMD中找到指向页面表PTE;
  3. 用线性地址中第三位段为下标在页面表中找到相应的表项,该表项中存放的就是指向物理页面的指针;
  4. 用线性地址中最后位段为物理页面的相对位移量,位移加上物理页面的起始地址就得到相应的物理地址。

每个进程的局部段描述表LDT都作为一个独立的段存在,在全局段描述表GDT中要有一个表项指向该段起始地址。此外每个进程还有一个TSS结构(任务状态段)也是如此。段寄存器用作全局段描述表为13位,即8192个段表,除去系统开销(1项永为0,2和3项为内核代码段和数据段,4和5项当前进程的代码段等等)以外,还有8180个表项可以使用,所以理论上最大进程数量是4090

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值