为什么有两个重叠的数据段(例如在Linux内核中)?

时间:2016-08-04 08:39:11

标签: linux-kernel x86 operating-system kernel memory-segmentation

在Linux内核以及许多在线x86教程中,我看到人们建议使用两个代码段和两个数据段。我理解需要两个代码段,因为CPL需要与DPL完全匹配(对于不符合要求的段)。

但是,这些教程中没有一个(也没有任何关于StackOverflow的相关问题),具体说明为什么我们需要两个数据段。这些工作与代码段的工作方式不同,因为CPL = 0的进程可以访问DPL = 3的数据段。

如果我们在不同权限级别的进程之间切换,则有两个数据段的缺点是必须重新加载DS,ES等寄存器。

所以我的具体问题是:假设我们使用的是平面内存模型,所有代码和段完全重叠,它的用途和内核数据段的用途是什么,而不是只有一个用户数据段?

1 个答案:

答案 0 :(得分:5)

有一个解释here

引自英特尔手册(第5.7节)

  

当SS寄存器加载了堆栈段的段选择器时,也会发生权限级别检查   此处与堆栈段相关的所有权限级别必须与CPL匹配;也就是说,CPL,stacksegment选择器的RPL和堆栈段描述符的DPL必须相同。如果RPL和DPL不相等   对CPL,生成一般保护异常(#GP)。

强调我的

也就是说,SS需要从内核(或在交换机中)加载时 DPL 等于0的数据段。
这适用于32位模式。

在64位模式下,it is possible to use a NULL selector禁止任何运行时检查(包括前一个) 1

  

在64位模式下,处理器不会对NULL段选择器执行运行时检查。处理器呢   当尝试访问引用的段寄存器具有的内存时,不会导致#GP错误   NULL段选择器。

完整性,在执行堆栈操作时,所有相关信息地址大小操作数大小堆栈地址大小是要么从代码段恢复,要么隐式设置为64位。

1 如果我没记错的话,出于兼容性原因,64位模式仍然使用内核数据段。