Linux内核如何在用户模式和内核模式堆栈之间切换?

3

当系统调用或中断出现时,Linux内核如何在用户模式和内核模式堆栈之间切换?我的意思是确切的机制 - 用户模式堆栈指针发生了什么变化,内核模式堆栈指针从哪里来?硬件会执行什么操作,软件必须执行什么操作?

1个回答

8

以下所有单词都和x86有关。

我将描述整个系统调用路径,本答案将包含所需信息。

首先,您需要了解什么是interrupt descriptor table。这个表存储异常/中断向量的地址。系统调用是一种异常。为了引发异常,用户代码执行

int x

汇编指令。每个异常,包括系统调用,都有自己的编号。在x86 linux上看起来是这样的。
int 0x80

int指令是一个复杂的多步指令。以下是它的解释:

1.) 从IDT(IDT地址存储在特殊寄存器中)中提取描述符并检查CPL <= DPL。CPL是当前特权级,可以从CS寄存器中读取。DPL存储在IDT描述符中。 由此可知 - 您不能通过int指令直接从用户空间生成某些异常(例如页面故障)。如果尝试这样做,将会得到一般保护异常

2.) 处理器切换到在TSS中定义的堆栈。 TSS已经初始化,并且已经包含了ESP和SS的值,这些值保存了内核堆栈地址。因此,现在ESP指向内核堆栈。

3.) 处理器将用户空间寄存器ss、esp、eflags、cs、eip推送到新切换的内核堆栈中。我们需要在系统调用服务后返回,对吧?

4.) 接下来处理器从IDT描述符中设置CS和EIP。该地址定义了异常向量入口点。

5.) 现在我们处于内核中的系统调用异常向量。


关于ARM的几句话。ARM没有TSS,而是有分别针对SVC和USR模式的堆栈指针。如果您感兴趣,可以查看陷阱入口代码

有趣的链接: MIT JOS实验室3XV6手册


非常有帮助。谢谢 @alex-hoppus - undefined
@Alex Hoppus,在你所提到的第一步中,CPU是否将其CPL更改为内核模式? - undefined
@AyoubOmari 在第4步完成了,正如你所看到的,当从描述符加载cs时。 - undefined
@AlexHoppus 是的,我在上次提问后明白了那个。非常有启发的答案,谢谢! - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接