当A进程运行到一半触发系统调用或被中断时,进行中断上下文的切换,之后执行ISR中断服务例程,在中断处理结束后,返回前,是进程调度的时机,使用_schedule()函数进行进程切换。
_schedule()函数首先从CPU任务队列中取出当前进程的标识符记为prev进程。然后通过进程调度算法确定下一个要被换上的进程,记为next进程。之后,检查next如果和prev进程不一样,调用context_switch()函数进行上下文切换,next进程进入CPU运行。
在context_switch()中调用switch_to()进行寄存器和堆栈的切换,switch_to()会调用_switch_to_asm()函数,在_switch_to_asm()的中进行了从prev内核堆栈到next内核堆栈的切换,在最后不使用ret指令,而是通过jmp指令跳转到_switch_to()函数,在_switch_to()函数的结尾调用return返回,因为在_switch_to_asm()中进行了堆栈的切换,因此_switch_to()返回后,回到的是next进程的内核堆栈,而不是prev进程的内核堆栈。
/*
* %eax: prev task
* %edx: next task
*/
ENTRY(__switch_to_asm)//_switch_to_asm()函数
......
/* switch stack */
movl %esp, TASK_threadsp(%eax)
movl TASK_threadsp(%edx), %esp
......
jmp __switch_to
END(__switch_to_asm)
进程切换结束后,中断返回,返回到了next进程进行运行。
函数调用顺序为: