📜  什么是全局描述符表

📅  最后修改于: 2022-05-13 01:57:02.294000             🧑  作者: Mango

什么是全局描述符表

全局描述符表:

  • 全局描述符表是 Intel x86 系列处理器使用的一种数据结构,从 80286 开始,用于定义程序执行期间使用的各种内存区域(段)的特征,包括大小、基址,以及访问权限,如写入和可执行。
  • 英特尔公司是一家美国科技公司和跨国公司。它的总部位于加利福尼亚州圣克拉拉的硅谷。英特尔公司是全球最大的半导体芯片制造商。它还开发 x86 系列微处理器。
  • x86 是在大多数个人计算机 (PC) 中使用的一系列微处理器。
  • 英特尔 80286 也被称为 iAPX 286[4] 或英特尔 286 它是 1982 年 2 月 1 日推出的 16 位微处理器。它是第一个基于 8086 的 CPU,具有独立的数据总线和非复用地址。它也是第一个具有内存管理和广泛保护能力的 CPU。

结构 :
确切地说,在保护模式下,在英特尔架构中,中断服务程序和内存管理基本上是由描述符表管理的。每个描述符都保存有关单个对象的信息,例如; CPU 有时可能需要的任务、服务例程、数据或代码的一部分等。如果有人试图将新值填充到段寄存器中,则 CPU 需要执行安全和访问控制检查,以查看您是否真的被允许访问该指定的内存区域。如果这些检查成功执行,那么有用的值将缓存在 CPU 的不可见寄存器中。 Intel 表示如下 3 种类型的表。

  1. 中断描述符表(替换 IVT)
  2. 全局描述符表 (GDT)
  3. 本地描述符表 (LDT)

笔记 -
上面所有的表都表示为一个线性地址,大小由 LIDT、LGDT、LLDT 指令依次向 CPU 表示。在大多数情况下,操作系统会在启动时直接通知这些表的位置,然后很明显,操作系统会通过指针写入或读取表。

GDT 概述:
全局描述符表携带向 CPU 告知内存段的条目。它是 IA32 架构特有的。

作品 :
在这里,我们将逐步了解GDT的组成如下。
第1步 :
通过使用 LGDT 汇编指令,加载 GDT。它寻找 GDT 描述结构的位置。 :

GDTR

第2步 :
这里的Offset是描述符表的线性地址,意思是分页,这里的Size是描述符表的大小减1。描述符表的大小减1,因为65535是大小的最大值,但 GDT 最多只能是 65536 字节(这意味着条目最多可以是 8192)。此外,没有 GDT 可以携带 0 的大小。

第 3 步:
GDT 包含 8 字节条目,每个条目具有如下复杂结构。

GDT 条目

第4步 :
这里,Limit 0:15 表示该字段携带 0-15 位的限制值。基数具有 32 位值,其中包含段开始的线性地址,此处的 20 位值表示最大可寻址单元(以 1 字节为单位或以页为单位)。因此,如果有人选择了 4 KiB 这样的页面粒度,然后将限制值设置为 0 × FFFFF,那么这里的段将长度为 4 GiB 地址空间。以下是标志和访问字节的组成,如下所示。

GDT 位

第 5 步:
符号说明 –

  • 公关 –
    这意味着现在位。对于所有有效扇区,它应该是 1 位。
  • 特权——
    是特权的意思。它应该包含 2 位和环级别,其中 0 = 最高(内核)和 3 = 最低(用户应用程序)。
  • 小号——
    这意味着描述符类型。必须为数据段或代码设置它,并且应该为系统段(例如,任务状态段)设置为空。
  • 前任 -
    这意味着可执行位。如果 Ex 为 1,则可以执行该段中的代码(即代码选择器),如果 Ex 为 0,则它是数据选择器。
  • 直流 -
    表示方向位,也称为顺位位。它告诉方向。如果 DC = 0,则分段向上增长,如果 DC = 1,则分段向下增长(意味着限制小于偏移量)。

第 6 步:
代码选择器的一致性位 -
如果给定段中的 1 个代码是从相同或更低的特权级别执行的。例如,环 3 中的代码远跳转到环 2 段中的符合代码。 privl 位显示允许执行段的最高权限级别。例如,环 0 中的代码不能远跳转到 privl == 0 × 2 的符合代码段,但环 2 和环 3 中的代码可以做到这一点。因此,特权级别保持不变,即从环 3 到 privl == 2 的远跳——跳转后段仍保留在环 3 中。如果为 0,则该段中的代码只能从 privl 中设置的环中执行。

第 7 步:
符号说明 –

  • RW –
    它表示可读位或可写位。
  1. 代码选择器的可读位:
    允许对该段进行以防万一的读取访问。不允许对代码段进行写访问。
  2. 数据选择器的可写位:
    如果允许对该段进行写访问。始终允许对数据段进行读取访问。
  • 交流 -
    这意味着访问位。将其设置为 0。当访问该段时,CPU 将其设置为 1。
  • 克-
    这意味着粒度位。如果为 0,则限制为 1 B 块(字节粒度),如果为 1,则限制为 4 KiB 块(页粒度)。
  • 大小 -
    这意味着大小位。如果为 0,则选择器定义 16 位保护模式。如果为 1,则选择器定义 32 位保护模式。我们可以同时拥有 16 位和 32 位选择器。

GDT 中保存的内容:
为了保持平衡,应始终将以下项目存储在 GDT 中,如下所示。

  • 处理器根本不引用 Null Descriptor。一些仿真器(例如——Bochs)会抱怨限制中的异常。该描述符还用于存储指向 GDT 本身的指针(与 LGDT 指令一起使用)。指针为 6 字节宽,空描述符为 8 字节宽。因此,GDT 可能是实现此目的的理想场所。
  • TSS 段描述符(至少保留一个位置)。
  • 数据段描述符(我们无法写入代码段,因此,我们将其添加到 type = 0 × 92)。
  • 代码段描述符(对于内核,它必须具有 type = 0 × 9A)。
  • 如果我们需要,可以为更多的细分留出空间(例如——LDT、用户级、更多的 TSS 等)。