手机版 欢迎访问it开发者社区(www.mfbz.cn)网站

当前位置: > 开发

2.2 保护模式下的段机制

时间:2021/3/30 3:30:38|来源:|点击: 次

1.一切从hello world说起

#include <stdio.h>
int main(void)
{
	printf("hello world!\n");
	return 0;
}
  • 我们通过编译,汇编,链接,装载并执行
    1. gcc -S hello.c -o hello.s //编译
    2. gcc -c hello.s -o hello.o //汇编
    3. gcc -c hello.o -o a.out //链接
    4. ./a.out //装载并执行
  • 图解如下
    在这里插入图片描述

2. 问题

  • 由上述编译,汇编,链接,装载并执行的过程引入几个问题

2.1 链接以后形成的地址是虚地址还是实地址?

  • 我们可以通过objdump -d a.out对可以执行程序进行反汇编。如下图:
    在这里插入图片描述
  • 可以看出最左边那一栏是虚地址,中间是机器码,右边是汇编指令。
  • 所以链接后形成的地址是虚地址。

2.2 装入程序把可执行代码装入到虚拟内存还是物理内存?

  • 通过readelf a.out -h 可以看到如下图:
    在这里插入图片描述
  • 可以得出程序被装载到0x400430的地址加载,这显然是一个虚拟内存。
  • 有些装载器会将入口地址进行修改,进行重定位,但依旧是虚拟内存。

2.3 CPU访问的是虚地址还是物理地址?

  • 由2.1可知,由编译链接后的形成的虚地址就是CPU要访问的地址。
  • CPU拿到虚地址后,需要经过mmu的转化,才能将物理地址送给存储器,如下图所示:
    在这里插入图片描述
  • 那么MMU中又包含了什么?

3.MMU的地址转换

在这里插入图片描述

3.1 MMU第一阶段

  • MMU通过段机制将虚拟地址转变成线性地址。

3.2 MMU第二阶段

  • MMU通过分页机制将线性地址转变成物理地址。

4. 虚拟-线性地址的转换

在这里插入图片描述

  • 虚拟地址空间中LimitB段映射到线性地址空间就是BaseB+LimitB——BaseB
  • 如何描述这种转换关系呢?——>段描述符表—段表来描述。

4.1 段描述符表——段表

  • 段号:描述的是虚拟地址空间段的编号。
  • 基地址:是线性地址空间段的起始地址。
  • 段描述符表中的每一个表项叫做段描述符。
  • 段表可以描述成下表的样子
    在这里插入图片描述

4.2 段描述符——描述段的结构

在这里插入图片描述

5. 保护模式下段寄存器存放什么

  • 实际上段寄存器存放在段号如下图
    在这里插入图片描述
  • RPL表示请求者的特权级(Requestor Privilege Level),保护模式下提供了4个特权级如图:
    在这里插入图片描述
  • 而linux中只用了两个特权级即最低(用户态)和最高(内核态)特权级。
  • TI表示段描述表的索引。来表示该表是全局描述符表还是局部描述符表。

6. 保护模式下的其他描述符表简介

  • 全局描述符表GDT(Gloable Descriptor Table)

  • 中断描述符表IDT(Interrupt Descriptor Table)

  • 局部描述符表LDT(Local Descriptor Table)

7. Linux中的段

  • 在众多架构中,往往支持页的机制,而不支持段的机制,Linux为了兼容,巧妙的绕过了段的机制。
  • 我们知道线性地址=段起始地址+偏移量。当段起始地址为0时,就可以巧妙的绕过段机制。
  • Linux在启动的过程中设置了段寄存器的值和全局描述符表GDT的内容,内核代码中可以这样定义段:
#define __KERNEL_CS     0x10/*内核代码段,index=2,TI=0,RPL=0*/
#define __KERNEL_DS     0x18/*内核数据段,index=3,TI=0,RPL=0*/
#define __USER_CS       0x23/*用户代码段,index=4,TI=0,RPL=3*/
#define __USER_DS       0x2B/*用户数据段,index=5,TI=0,RPL=3*/

8. 带着问题离开

8.1 在硬件设计中操作系统设计中,到底进行怎样的取舍和折中?

  • 就这篇文章中
    • 对于特权级,简化为两级是为了操作系统的简洁性。
    • 对于段机制,为了兼容其他架构舍弃了段机制。
    • 对于内存寻址,为了解决多程序内存地址冲突,和安全性引入了保护模式,但相比于直接寻址,可能还耗费时间的。这时选择相对比较快速的寻址算法就很重要了。——>查表就是一种算法寻址的算法。

Copyright © 2002-2019 某某自媒体运营 版权所有