进程上下文和中断上下文

linux0.11系统共使用了四种堆栈

一种是系统初始化时临时使用的堆栈

一种是供内核程序自己使用的堆栈(内核堆栈),只有一个位于系统地址空间固定的位置,也是后来任务0的用户态堆栈。

一种是每个任务通过系统调用,执行内核程序时使用的堆栈,我们称之为任务的内核态堆栈,每个任务都有自己独立的内核态堆栈。

一种是任务在用户态执行的堆栈,位于任务(进程)地址空间的末端,称为用户态堆栈

任务的堆栈

每个任务都有自己的内核态堆栈,与每个任务的任务数据结构(task_struct)放在同一页中.

这是在建立新任务时,fork()程序在任务状态段tss(只是一个位于内存的结构体里面存着eip esp...)的

内核级堆栈字段(tss.esp0和tss.ss0)中设置的。

进程上下文和中断上下文

任务0的堆栈

任务0的堆栈比较特殊,任务0的数据段和代码段相同,段基地址都是从0开始,限长也都是640K。

这个地址范围也就是内核代码和数据所在的地方。在执行了move_to_user_mode()之后,他的内核堆栈位于其任务数据结构所在页面的末端,而他的用户态堆栈就是前面进入保护模式后所使用的堆栈 ,即sched.c的user_stack数组的位置。

任务0的内核态堆栈是在其人工设置的初始化任务数据结构中指定的,而他的用户态堆栈是在执行move_to_user_mode()时,在模拟iret返回之前的堆栈中设置的。

iret具体作用:中断的返回,具体是返回标志寄存器CS IP

复习一下寄存器:

CS DS SS ES都是段寄存器

AX BX CX DX通用寄存器

在内核里面指向内核栈:SS:堆栈段   ESP:堆栈指针

SS:记录的是段选择器,用户程序不可以进程修改

ESP:指向堆栈内部特定位置的32位的指针。

代码指令就是CS:代码段  EIP:指令地址寄存器

 

内核态与用户态堆栈的切换

任务调用和系统调用时就会进入内核,执行内核代码。

此时内核代码就会使用该任务的内核态堆栈进行操作。

当进入内核程序时,由于优先级发生了改变(从用户态转到内核态),用户态堆栈的堆栈段和堆栈指针以及eflags会被保存在人物的内核态堆栈中。而在执行iret推出内核程序,回到用户程序时,将恢复用户态堆栈的堆栈和eflags。

进程上下文和中断上下文

当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。

当内核需要切换到另一个进程时,它需要保存当前进程的所有状态,即保存当前进程的上下文,以便在再次执行该进程时,能够必得到切换时的状态执行下去。在LINUX中,当前进程上下文均保存在进程的任务数据结构中。

在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。但同时会保留所有需要用到的资源,以便中继服务结束时能恢复被中断进程的执行