Linux内核如何在用户模式和内核模式堆栈之间切换? [英] How does linux kernel switch between user-mode and kernel-mode stack?

查看:94
本文介绍了Linux内核如何在用户模式和内核模式堆栈之间切换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How does linux kernel switch between user-mode and kernel-mode stack when a system call or an interrupt appears? I mean what is the exact mechanism - what happens to user-mode stack pointer and where does kernel-mode stack pointer come from? What is done by hardware and what must be done by software?

推荐答案

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

All of the words below are about x86.

我将仅描述整个系统调用路径,并且此答案将包含所需的信息.

I will just describe entire syscall path, and this answer will contain requested information.

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

First of all, you need to understand what is interrupt descriptor table. This table stores addresses of exception/interrupts vectors. System call is an exception. To raise an exception user code perform

int x

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

assembly instruction. Each exception including system call have its own number. On x86 linux this will be look like

int 0x80

int指令是一个复杂的多步指令.这是它的作用的解释:

The int instruction is a complex multi step instruction. Here is an explanation of what it does:

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

1.) Extracts descriptor from IDT (IDT address stored in special register) and checks that CPL <= DPL. CPL is a current privilege level, which could be read from CS register. DPL is stored in the IDT descriptor. As a consequence of this - you can't generate some exceptions (f.e. page fault) from user space directly by int instruction. If you will try to do this, you will get general protection exception

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

2.) The processor switches to the stack defined in TSS. TSS was initialized earlier, and already contains values of ESP and SS, which holds the kernel stack address. So now ESP points to kernel stack.

3.)处理器将新切换的内核堆栈用户空间寄存器压入: ss,esp,eflags,cs,eip .我们需要在调用syscall后返回,对吗?

3.) The processor pushes to the newly switched kernel stack user space registers: ss, esp, eflags, cs, eip. We need to return back after syscall is served, right?

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

4.) Next processor set CS and EIP from IDT descriptor. This address defines exception vector entry point.

5.)这是内核中的syscall异常向量.

5.) Here we are in the syscall exception vector in kernel.

关于ARM的几句话.ARM没有TSS,它禁止了每个模式的寄存器.因此,对于SVC和USR模式,您具有单独的堆栈指针.如果您有兴趣,可以查看捕获条目代码

And few words about ARM. ARM doesn't have TSS, it have bancked per-mode registers. So for SVC and USR modes you have separate stack pointers. If you are interested in you can take look at trap entry code

Interestring链接: MIT JOS实验3 XV6手册

Interestring links: MIT JOS lab 3 , XV6 manual

这篇关于Linux内核如何在用户模式和内核模式堆栈之间切换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆