读了很久,真的很迷茫。从我读到的:
现代操作系统根本不使用段。
GDT 用于在内存中定义一个段(包括约束)。
页表有一个主管位,指示当前位置是否用于内核。
维基百科说“GDT 仍然存在于 64 位模式;必须定义 GDT,但通常永远不会更改或用于分段。”
为什么我们需要它?以及linux如何使用它?
读了很久,真的很迷茫。从我读到的:
现代操作系统根本不使用段。
GDT 用于在内存中定义一个段(包括约束)。
页表有一个主管位,指示当前位置是否用于内核。
维基百科说“GDT 仍然存在于 64 位模式;必须定义 GDT,但通常永远不会更改或用于分段。”
为什么我们需要它?以及linux如何使用它?
- 现代操作系统根本不使用段。
现代操作系统(用于 64 位 80x86)仍然使用段寄存器;只是它们的使用对用户空间“大部分是隐藏的”(并且大多数用户空间代码可以忽略它们)。具体来说; CPU 将确定代码是 64 位(或 32 位还是 16 位),无论操作系统加载(从 GDT 或 LDT)到什么CS
,中断仍然保存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 等)。