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

mrn*_*mrn 2 linux linux-kernel

当系统调用或中断出现时,linux内核如何在用户模式和内核模式堆栈之间切换?我的意思是确切的机制是什么 - 用户模式堆栈指针会发生什么以及内核模式堆栈指针来自哪里?什么由硬件完成,什么必须由软件完成?

Ale*_*pus 7

下面的所有单词都是关于 x86 的。

我将只描述整个系统调用路径,这个答案将包含请求的信息。

首先,您需要了解什么是中断描述符表。该表存储异常/中断向量的地址。系统调用是一个例外。引发异常用户代码执行

int x
Run Code Online (Sandbox Code Playgroud)

组装说明。每个异常包括系统调用都有自己的编号。在 x86 linux 上,这看起来像

int 0x80
Run Code Online (Sandbox Code Playgroud)

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

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

2.) 处理器切换到TSS 中定义的堆栈。TSS 较早初始化,并且已经包含 ESP 和 SS 的值,它们保存内核堆栈地址。所以现在 ESP 指向内核堆栈。

3.)处理器推到新交换内核栈用户空间寄存器:ss, esp, eflags, cs, eip。我们需要在 syscall 服务后返回,对吗?

4.) 下一个处理器集来自 IDT 描述符的 CS 和 EIP。该地址定义了异常向量入口点。

5.) 这里我们在内核中的系统调用异常向量中。


以及关于 ARM 的几句话。ARM 没有 TSS,它有每个模式的寄存器。因此,对于 SVC 和 USR 模式,您有单独的堆栈指针。有兴趣的可以看看trap入口代码

有趣的链接: MIT JOS lab 3XV6 手册