linux - 全局描述符表(GTD)的现代用法是什么?
问题描述
读了很久,真的很迷茫。从我读到的:
现代操作系统根本不使用段。
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 等)。
推荐阅读
- android - 使用 Jetpack compose 检测 RadioButton 中选择了什么答案
- r - 如何根据不同列的值从一列中选择值?
- sqlite - Tcl StarKit 与 SQLite 数据库作为程序?
- xml - xmlMapper 找不到字符串创建者
- apache-flink - 每个保存点结束后内存都会增加一点
- android - 构建失败 D:\My Folder\Android\Android SDK\tools\ant\build.xml:538: 无法解析项目目标“Google Inc.:Google APIs:13”
- python - 如何按 id 分组以使所有数据集成为一个数据集
- javascript - 即使数据确认存在于前一行,也会出现此错误!我错过了吗?TypeError:无法读取未定义的属性“包含”
- excel - Excel VBA从另一个excel中获取数据,源数据的路径作为变量
- rust - Rust Diesel sql_query 带有返回的插入示例