1.进程切换是指:保存prev进程的上下文,用next的上下文替代。
其中上下文包括:页全局目录、内核态堆栈、硬件上下文。
2.80x86为进程切换提供的硬件支持:
第一种:通过任务门
第二种:通过JMP和CALL指令:把硬件上下文存在TSS中,执行这条指令时,通过硬件自动切换TSS,完成硬件上下文的过程
TSS是任务状态段,只能存放在GDT中,不能存放在LDT中
3.Linux使用的硬件上下文切换方法:
通过一组MOV指令逐步执行切换,手动模拟1的过程
因为这样效率较高,也便于各种检查和保护
4.Linux的进程切换不使用80x86提供的硬件方法,但是为了与80x86兼容,仍会为每个CPU创建一个TSS(按照80X86,应该是为每个进程创建一个),供当前运行的进程使用。
每当切换进程时,更新TSS中的内容(按照80X86,应该是切换TSS)
5.内核堆栈与硬件上下文的切换是由宏switch_to()完全的,这段程序短小精悍,很重要。可惜汇编没学好
(1)把prev和next的值分别保存到EAX和EDX中
(2)把EFLAGS和EBP的内容保存到prev内核栈中
(3)ESP的内容保存到prev->thread.esp中
(4)next->thread.esp的内容装入ESP中//从现在开始,当前堆栈是next的内核堆栈
(5)把标记为1的地址存入prev->thread.eip
(7)把next->thread.eip的值压入next的内核堆栈//这个值往往是标记为1的地址,这是最后入栈的,因此从下面的一个调用返回后,会执行标记为1的程序
(8)__switch_to():主要是针对TSS的操作,见6
(9)标号为1的指令:弹出EFLAGS和EBP
(10)将EAX的内容拷贝到last标识的区域中
switch_to(prev, next, last)
这个函数有三个参数,
第一个参数和第二参数都是输入参数,分别表示被替换的进程和新的进程的位置。
第三个参数是输出参数,记录被替换的进程被替换到的位置,见程序中的EAX
6.__switch_to()
(1)有选择地保存prev_p的FPU、MMX、XMM等寄存器
(2)把next_p->thread.esp0装入TSS的esp0中
(3)把next_p进程使用的线程局部存储段装入本地CPU的GDT
(4)加载next进程的fs段和gs段
(5)更新TSS的I/O位图
(6)ret,返回到栈中标号为1的指令