当系统调用或中断出现时,linux内核如何在用户模式和内核模式堆栈之间切换?我的意思是什么是确切的机制 - 用户模式堆栈指针会发生什么以及内核模式堆栈指针来自何处?硬件做了什么,软件必须做什么?
答案 0 :(得分:4)
以下所有字词均为x86。
我将描述整个系统调用路径,此答案将包含所请求的信息。
首先,您需要了解interrupt descriptor table是什么。该表存储异常/中断向量的地址。系统调用是一个例外。要引发异常用户代码,请执行
int x
装配说明。每个例外,包括系统调用都有自己的编号。在x86 linux上,这将看起来像
int 0x80
int指令是一个复杂的多步指令。以下是对其作用的解释:
1。)从IDT中提取descriptor(存储在特殊寄存器中的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.)这里我们在内核的syscall异常向量中。
关于ARM的话很少。 ARM没有TSS,它已经禁止每模式寄存器。因此,对于SVC和USR模式,您有单独的堆栈指针。如果您对此感兴趣,请查看trap entry code
Interestring链接: MIT JOS lab 3, XV6 manual