Linux 分段

Linux Segmentation

最近,我读了一本书叫理解linux内核。有一句话让我很困惑。谁能给我解释一下?

As stated earlier, the Current Privilege Level of the CPU indicates whether the processor is in User or Kernel Mode and is specified by the RPL field of the Segment Selector stored in the cs register. Whenever the CPL is changed, some segmentation registers must be correspondingly updated. For instance, when the CPL is equal to 3 (User Mode), the ds register must contain the Segment Selector of the user data segment,but when the CPL is equal to 0, the ds register must contain the Segment Selector of the kernel data segment.

A similar situation occurs for the ss register. It must refer to a User Mode stack inside the user data segment when the CPL is 3, and it must refer to a Kernel Mode stack inside the kernel data segment when the CPL is 0. When switching from User Mode to Kernel Mode, Linux always makes sure that the ss register contains the Segment Selector of the kernel data segment.

When saving a pointer to an instruction or to a data structure, the kernel does not need to store the Segment selector component of the logical address, because the ss register contains the current Segment Selector.

As an example, when the kernel invokes a function, it executes a call assembly language instruction specifying just the Offset component of its logical address; the Segment Selector is implicitly selected as the one referred to by the cs register. Because there is just one segment of type “executable in Kernel Mode,” namely the code segment identified by __KERNEL_CS, it is sufficient to load __KERNEL_CS into cs whenever the CPU switches to Kernel Mode. The same argument goes for pointers to kernel data structures (implicitly using the ds register), as well as for pointers to user data structures (the kernel explicitly uses the es register).

我的理解是 ss 寄存器包含指向堆栈底部的段选择器。 ss 寄存器与指向影响数据结构的指令的指针有什么关系吗?如果不是,为什么要在这里提到它?

My understanding is the ss register contains the Segment Selector point to the base of the stack.

Does ss register have anything to do with the pointer to an instruction to to a data structure?

不,ss寄存器与影响数据段的指令没有任何关系。

If it doesn't, why mention it here?

因为 ss 寄存器会影响影响堆栈的指令的结果(例如:poppush 等)。

他们只是在解释 Linux 还维护两个堆栈段(一个用于用户模式,一个用于内核模式)以及两个数据段(一个用于用户模式,一个用于内核模式) .

至于数据段如果从用户态切换到内核态时不更新,ss选择器仍然指向用户栈,内核将与用户栈一起工作(会很糟糕,对吧?) .所以内核负责更新 ss 寄存器和 ds 寄存器。

注意: 让我们回想一下,一条指令可能 access/modify 位在数据段(mov 到内存地址,)以及堆栈段(poppush 等。 )

终于把那段话的意思说清楚了。实际上,这段描述演示了分段在 Linux 中的工作原理。它确实具有隐含的比较对象——那些系统利用分段而不是分页。这些系统如何运作?每个进程在其逻辑地址中都有不同的段选择器,这些段选择器指向全局描述符 table 中的不同条目。每个片段不一定需要具有相同的碱基。在那种情况下,当您保存指向指令或数据结构的指针时,您确实必须处理它的段基址。请注意,每个逻辑地址都有一个 16 位段选择器和一个 32 位偏移量。如果只保存偏移量,就不可能再次找到那个指针,因为 GDT 中有很多不同的段。当涉及到 Linux 时,情况就不同了。所有段选择器都有相同的基数 0。这意味着指针的偏移量足够特殊,可以从内存中获取它。你可能会问,那里有很多进程运行 是否有效?有用!请记住,每个进程都有其 Page Table,它具有将相同地址映射到不同物理地址的神奇力量。感谢所有关心这个问题的人!