【问题标题】:What is the modern usage of the global descriptor table(GTD)?全局描述符表(GTD)的现代用法是什么?
【发布时间】:2020-11-08 18:30:09
【问题描述】:

读了很久,我真的很困惑。 从我读到的:

  1. 现代操作系统根本不使用段。

  2. GDT 用于在内存中定义一个段(包括约束)。

  3. 页表有一个主管位,指示当前位置是否用于内核。

  4. 维基百科说“GDT 仍然存在于 64 位模式;必须定义 GDT,但通常永远不会更改或用于分段。”

我们为什么需要它?以及linux是如何使用它的?

【问题讨论】:

    标签: linux operating-system gdt


    【解决方案1】:
    1. 现代操作系统根本不使用段。

    现代操作系统(用于 64 位 80x86)仍然使用段寄存器;只是它们的使用对用户空间“大部分是隐藏的”(并且大多数用户空间代码可以忽略它们)。具体来说; CPU 将根据操作系统加载(从 GDT 或 LDT)到 CS 的任何内容来确定代码是否为 64 位(或 32 位或 16 位),中断仍会保存 CSSS 用于被中断的代码(并在iret 再次加载它们),GS 和/或FS 通常用于线程本地和/或 CPU 本地存储等。

    1. GDT 用于在内存中定义一个段(包括约束)。

    代码和数据段只是 GDT 的用途之一。另一个主要用途是定义任务状态段的位置(用于查找 IO 端口权限映射、当中断导致特权级别更改时加载到 CS、SS 和 RSP 中的值等)。 64 位代码(以及在 64 位内核下运行的 32 位代码/进程)仍然可以使用 GDT 中定义的调用门,但大多数操作系统不使用该功能来处理 64 位代码(他们改用syscall)。

    1. 页表有一个主管位,指示当前位置是否用于内核。

    是的。页表的主管位确定在 CPL=3 下运行的代码是否可以/不能访问该页(或者代码是否必须为 CPL=2、CPL=1 或 CPL=0 才能访问该页)。

    1. 维基百科说“GDT 仍然存在于 64 位模式中;必须定义 GDT,但通常永远不会更改或用于分段。”

    是的 - 维基百科是正确的。通常,操作系统会在启动的早期设置 GDT(用于 TSS、CS、SS 等),然后在启动后没有任何理由修改它;并且段寄存器不用于“分段内存保护”(但用于其他事情 - 确定代码大小,中断处理程序是否应返回 CPL=0 等)。

    【讨论】:

    • 谢谢! 1.我们检查GDT时能举个例子吗? 2.DPL保存在GDT中,所以当我们检查它的时候呢?(如果我们有分页的内存保护,我们为什么需要它?)
    • 3.我们什么时候检查代码大小?为什么我们需要这样做? 4.是否每个内存引用都通过 GDT?例如 CS::1000,去 GDT 并检查相关位? 1000(内存参考)呢?
    • @MosheLevy:当大多数事情(显式加载、中断、“远”控制传输,但不是syscall)导致将值加载到段寄存器中时; CPU 从 GDT(或 LDT)获取信息并检查该信息。如果没有问题(没有一般保护错误),则信息将缓存在 CPU 中(在段寄存器的“隐藏”部分)以供后续使用(例如,CPU 不必不断检查代码段的 GDT 条目每次它解码一条指令)。
    • @MosheLevy:DPL 仅用作“当值加载到段寄存器时 CPU 检查来自 GDT/LDT 的信息”检查的一部分;确定当前运行的代码是否具有使用 GDT/LDT 条目所需的权限。
    猜你喜欢
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    • 1970-01-01
    • 1970-01-01
    • 2015-06-08
    • 1970-01-01
    相关资源
    最近更新 更多