FS 和 GS 寄存器在线性地址 space 中映射到哪里?

Where do FS and GS registers get mapped to in the linear address space?

我知道在 32 位中你有段,每个段都会映射到一个基数和限制。因此,一个段将无法访问另一个段的数据。

对于 64 位,我们丢弃了大部分段并以 0 为基数,没有限制,因此可以访问整个 64 位地址 space。但是当他们说我们有 FS 和 GS 寄存器用于线程本地存储和附加数据时,我感到困惑。

如果默认段可以访问线性地址 space 中的任何内容,那么是什么阻止程序破坏或访问 FS/GS 段? OS 必须跟踪 FS/GS 并确保没有其他分配在那里,对吗?这是如何工作的?

此外,如果默认区域可以访问任何内容,那我们为什么还要FS/GS。我想 FS 是有道理的,因为我们可以在线程切换期间切换寄存器。但为什么还要使用 GS?为什么不用 malloc 内存呢?抱歉,我是 OS.

的新手

在 64 位模式下,FS 和 GS“段寄存器”本身并没有真正被使用。但是使用 FS 或 GS​​ 段覆盖进行内存访问会导致地址被隐藏 FSBASE/GSBASE 寄存器中包含的值偏移,该寄存器可以由特殊指令设置(可能是特权指令,在这种情况下,系统调用可以要求内核来做)。因此,例如,如果 FSBASE = 0x12340000 且 RDI = 0x56789,则 MOV AL, FS:[RDI] 将从线性地址 0x12396789.

加载

这仍然只是一个线性地址 - 它与进程地址的其余部分 space 没有任何区别,并且它与任何其他内存访问一样受到所有相同的分页和内存保护。该程序可以获得与 MOV AL, [0x12396789] 完全相同的效果(因为 DS 的基数为 0)。如果程序打算以这种方式使用 FS,则由程序通常的内存分配机制来分配适当的内存块并将 FSBASE 设置为指向该块。不需要特殊保护来避免“损坏”此内存,就像它们不需要防止程序损坏其自身内存的任何其他部分一样。

所以它并没有真正提供新的功能——它更多的是为程序员和编译器提供便利。正如你所说,它对于像指向线程本地存储的指针这样的东西很好,但是如果我们没有 FS/GS,我们还有很多其他方法可以将这样的指针保持在线程的状态中(比如,保留R15).的确,对 两个 这样的寄存器没有明显的普遍需求;在大多数情况下,另一个只是为了防止有人想出在特定程序中使用它的好方法。

另请参阅:

  • How are the fs/gs registers used in Linux AMD64?

  • What is the "FS"/"GS" register intended for?