通俗理解操作系统:全局描述符表(GDT)与 GDTR 详解
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
通俗理解操作系统:全局描述符表(GDT)与 GDTR 详解
前言
近来学习操作系统,操作系统知识错综复杂,而大多教程却默认学习者拥有相应知识储备,GTD、LDT、TSS便是我的第一拦路虎。
一、在开始之前先补充一些知识(因为我当时确实不知道或是混淆了)
描述符:
一条完整 8 字节描述符包含三样核心内容:目标起始地址 Base,可用边界 Limit,各类权限与类型属性
简单来说就是用来定位我们要操作的目标的,同时具有目标的基本信息,防止我操作越界等问题。
二、GDT 全局描述符表
结构图如下(示例):
图一
图二
很多人会疑惑两张图怎么不一样,实际上它们都表示 GDT 结构的不同划分,图二其实是将原本在同一类别的数据位数如 Base 统计了一下。
但这些数据在内存中的摆放仍是按照图一,我个人甚至认为图二甚至有混淆的作用。
!!!注意:这里的图不过是 GDT 中的一项,GDT 其中包含了很多这样的项。
既然知道了什么是 GDT,那么现在就要用了,首先我们要先补充一下知识。
8086 cpu在实模式下寻址方式是采用20位地址,16位寻址方式 ds:ax,ds是段寄存器 ,ax是随便
一个寄存器表示偏移量,也就是目标地址=ds左移4位+ax就是我们的目标地址
它的寻址能力就是 ax也就是偏移量
XX位寻址方式就代表着我们可以根据一个段,通过设置偏移量找到2的XX次个连续的地址(个人理解,不是很严格的定义)。
但随着计算机发展20位地址的寻址能力不再满足我们的需求,我们开发了32位寻址方式,我们开发了32位寻址方式系统,ax完美升级为eax变为32位,但ds寄存器仍然是16位,你问为啥ds不升级为32位,答案是兼容,包括前面实模式为啥是采用20位地址,16位寻址方式寻址,20位也不是2的幂。
32位寻址方式,我们的段肯定要有32位,但我们的ds寄存器只有16位,为了实现32位寻址,我们让CPU进入保护模式,处于保护模式时CPU接收地址从原本 ds:ax 变为ds:eax,但偏移地址我们不再只使用eax的低16位,而是 32位,这样我们的cpu寻址能力就达到了4gb(2^32),这是偏移地址。
段地址该怎么办呢,就是靠我们的主角GDT了,我们要做的就是用ds在GDT中查表拿到我们的目标地址,
注意千万不要把GDT当作一个表内项地址连续的表,表中的地址全部由程序员任意设置,我想定位0-到4gb这段内存,那我就设个表项指向0处即可,也就是我们根据ds找到在GDT表中的第几项,然后与将取出来的地址seg+eax,就得到了我们的目标地址
ds此时为段选择子:段选择子包括三部分:描述符索引(index)、TI(指示从GDT还是LDT中找)、请求特权级(RPL),它的16位二进制数不仅包含了目标段在GDT中的项数,还包含了这些其他信息
GDTR
全局描述符表 GDT(Global Descriptor Table)在整个系统中,全局描述符表 GDT 只有一张(一个处理器对应一个 GDT),GDT 可以被放在内存的任何位置,这是我抄录别人的描述
这时会感到疑惑,你不是内存允许随便放,随便写,怎么还限制只能存在一个,事实上你的 GDT 表在内存上写多少份都无所谓,但计算机不会在你用到时自动把表送到你面前,我们必须要通过一个入口进入即 GDTR —— 1 个计算机专门为存放 GDT 开始地址的寄存器,我们把 GDT 开始地址存放进去,这个寄存器只有一个,所以即使你内存中再多和 GDT 一样格式的数据,但没有 GDTR 你找不到,
本文章参考了 https://zhuanlan.zhihu.com/p/25867829,同时保护模式下,具体的怎么根据 ds 的 16 位数据找到对应哪个 GDT 表项,在他的文章中亦有叙述。
总结
没有总结,已被操作系统逼疯 ing。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)