我正在浏览GDT。我可以掌握数据结构是如何实现的及其目的。
但是,我不明白的是如何使用GDT。CPU 需要加载段的情况是什么,GDT 如何做到这一点?如果GDT涉及键盘驱动的中断,这将是一个很好的解释示例。
GDT 或全局描述符表包含有关内存段的信息。GDT的地址存储在称为GDTR的特殊寄存器之一中。每个段映射到一个内存区域。该段的目的是提供硬件内存保护。CPU 不会真正加载整个段,因为段通常是指内存区域。相反,当您使用带有偏移量的段寄存器(CS、DS、SS 等)之一来寻址内存区域时,CPU 将使用存储在 GDT 中的信息执行检查。例如,如果您将其中一个段设置为只读,然后您稍后尝试写入该段,则 CPU 将阻止访问。对于使用段的系统,每次有人访问内存时都会涉及GDT。
今天的操作系统很少使用分段。他们中的大多数人都建立了"平面内存模型",每个段跨越整个内存空间。分页和虚拟内存用于内存保护。段的存在主要是因为向后兼容。 您可以在osdev上阅读有关GDT的更多信息
对于不使用分段(太多)的现代操作系统; 您可能会发现 GDT 包含:
"CPL=0"和"CPL=3"代码- 的 2 或 3 个描述符(如果 64 位操作系统支持较旧的 32 位进程,则除了"64 位 CPL=0 代码"外,它还可能具有"32 位 CPL=3 代码"和"64 位 CPL=3 代码")
- "CPL=0"堆栈的描述符
- "CPL=3"堆栈和数据的描述符 CPU 的
- TSS(任务状态段)的每个 CPU 的描述符 对于
- 32 位(对于 64 位,您可以使用
swapgs
位)每个 CPU 一个或两个描述符,用于查找"CPU 本地"数据和/或"线程本地"数据 - (可选,不太可能);定义内核 API 调用入口的描述符
- (可选地,用于特殊目的);描述 LDT 的一个或多个描述符(有时用于仿真)
对于其他操作系统,GDT 可以包含任何内容。