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

标签 linux linux-kernel

当出现系统调用或中断时,linux内核如何在用户态和内核态堆栈之间切换?我的意思是确切的机制是什么——用户模式堆栈指针发生了什么,内核模式堆栈指针从哪里来?硬件能做什么,软件必须做什么?

最佳答案

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

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

首先你要明白什么是interrupt descriptor table .该表存储异常/中断向量的地址。系统调用是一个异常(exception)。引发异常用户代码执行

int x

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

int 0x80

int 指令是一个复杂的多步指令。以下是对其作用的解释:

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

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

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

4.) 下一个处理器根据 IDT 描述符设置 CS 和 EIP。该地址定义异常向量入口点。

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


还有关于 ARM 的几句话。 ARM 没有 TSS,它有 banked per-mode 寄存器。所以对于 SVC 和 USR 模式,你有单独的堆栈指针。有兴趣可以看看trap entry code

有趣的链接: MIT JOS lab 3 , XV6 manual

关于linux - linux内核如何在用户模式和内核模式堆栈之间切换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38360312/

相关文章:

linux - 如何列出组在 unix/linux 中有权访问的所有目录

linux - 如何在保留您键入的文字的同时打印新消息?

Git 全局标签--- 显然不好,但为什么呢?

linux - 到达ubuntu上linux内核源码的根目录?

c - 奇怪的 printk 对 linux 堆栈大小测试的影响

linux - 什么时候CPSR GE[3 :0] bits be modified

linux - ksh su -c 返回值

c 命令 system() 的输出可以进入文件而不是显示在控制台上吗?

linux - 如何在linux上用C控制硬盘电机速度?

Linux SLUB : Unable to allocate memory on node