【发布时间】:2020-11-08 18:30:09
【问题描述】:
读了很久,我真的很困惑。 从我读到的:
-
现代操作系统根本不使用段。
-
GDT 用于在内存中定义一个段(包括约束)。
-
页表有一个主管位,指示当前位置是否用于内核。
-
维基百科说“GDT 仍然存在于 64 位模式;必须定义 GDT,但通常永远不会更改或用于分段。”
我们为什么需要它?以及linux是如何使用它的?
【问题讨论】:
标签: linux operating-system gdt
读了很久,我真的很困惑。 从我读到的:
现代操作系统根本不使用段。
GDT 用于在内存中定义一个段(包括约束)。
页表有一个主管位,指示当前位置是否用于内核。
维基百科说“GDT 仍然存在于 64 位模式;必须定义 GDT,但通常永远不会更改或用于分段。”
我们为什么需要它?以及linux是如何使用它的?
【问题讨论】:
标签: linux operating-system gdt
- 现代操作系统根本不使用段。
现代操作系统(用于 64 位 80x86)仍然使用段寄存器;只是它们的使用对用户空间“大部分是隐藏的”(并且大多数用户空间代码可以忽略它们)。具体来说; CPU 将根据操作系统加载(从 GDT 或 LDT)到 CS 的任何内容来确定代码是否为 64 位(或 32 位或 16 位),中断仍会保存 CS 和 SS 用于被中断的代码(并在iret 再次加载它们),GS 和/或FS 通常用于线程本地和/或 CPU 本地存储等。
- GDT 用于在内存中定义一个段(包括约束)。
代码和数据段只是 GDT 的用途之一。另一个主要用途是定义任务状态段的位置(用于查找 IO 端口权限映射、当中断导致特权级别更改时加载到 CS、SS 和 RSP 中的值等)。 64 位代码(以及在 64 位内核下运行的 32 位代码/进程)仍然可以使用 GDT 中定义的调用门,但大多数操作系统不使用该功能来处理 64 位代码(他们改用syscall)。
- 页表有一个主管位,指示当前位置是否用于内核。
是的。页表的主管位确定在 CPL=3 下运行的代码是否可以/不能访问该页(或者代码是否必须为 CPL=2、CPL=1 或 CPL=0 才能访问该页)。
- 维基百科说“GDT 仍然存在于 64 位模式中;必须定义 GDT,但通常永远不会更改或用于分段。”
是的 - 维基百科是正确的。通常,操作系统会在启动的早期设置 GDT(用于 TSS、CS、SS 等),然后在启动后没有任何理由修改它;并且段寄存器不用于“分段内存保护”(但用于其他事情 - 确定代码大小,中断处理程序是否应返回 CPL=0 等)。
【讨论】:
syscall)导致将值加载到段寄存器中时; CPU 从 GDT(或 LDT)获取信息并检查该信息。如果没有问题(没有一般保护错误),则信息将缓存在 CPU 中(在段寄存器的“隐藏”部分)以供后续使用(例如,CPU 不必不断检查代码段的 GDT 条目每次它解码一条指令)。