调试分析 Linux 0.00 多任务切换
执行 153 行 iret 时栈的变化
执行前栈的内容
执行后栈的内容
在执行前后进行了栈的切换,从任务0的内核栈切换到了任务的用户栈。
模式切换
当进入和退出 system_interrupt
时,都发生了模式切换,请总结模式切换时,特权级是如何改变的?栈切换吗?如何进行切换的?
在进入中断时,通过查询IDT表,获得索引,之后进行特权级检查,要求CPL<=调用门DPL;RPL<=调用门DPL。DPL<=CPL。特权级检查通过,则特权级改变。栈也进行切换。处理器从当前任务的TSS段获得该中断使用的堆栈的段选择符与栈指针,然后把被中断的栈选择符与栈指针压入新栈。EFLAGES、CS、EIP的值也被压栈。
当退出时,使用iret指令。把保存的寄存器内容恢复到EFLAGES中,完成特权级复原,即切换为3。同时栈也切换回原来的栈。
任务切换过程
当时钟中断发生,进入到 timer_interrupt
程序,请详细记录从任务 0
切换到任务 1
的过程。
以本图为例分析。说明第一次切换时的状况,第一次切换,即时钟中断发生时,大概率会在227行,此时任务号为0,当跳入时钟中断后,从125行开始进行转换,首先将1写入寄存器eax,然后判断,因为此时任务号为0,所以不执行127行,执行128行,则将任务号改为1,然后在129行跳转到任务1的代码段。
任务0时的寄存器如下:
任务1时的寄存器如下:
任务切回过程
又过了 10ms
,从任务1切换回到任务 0
,整个流程是怎样的? TSS
是如何变化的?各个寄存器的值是如何变化的?
如图,承接上题叙述,从代码段228执行,在232循环,大概率在循环时进行时间中断发生,在126行比较时,由于此时任务号为1,所以跳转到131行,将任务号设为0,在132行处,跳转到任务0,由于任务0执行到129行,所以从130执行,再跳转到133行,弹栈后通过iret返回,由于上次为在226行触发中断,所以回到226行。
寄存器变化如下:
变至
下图为任务0的TSS
下图为任务1的TSS
详细总结任务切换的过程
还是对照这张图片,从头来讲。
第一次切换,即时钟中断发生时,大概率会在227行,此时任务号为0,当跳入时钟中断后,从125行开始进行转换,首先将1写入寄存器eax,然后判断,因为此时任务号为0,所以不执行127行,执行128行,则将任务号改为1,然后在129行跳转到任务1的代码段。
从代码段228执行,在232循环,大概率在循环时进行时间中断发生,在126行比较时,由于此时任务号为1,所以跳转到131行,将任务号设为0,在132行处,跳转到任务0,由于任务0执行到129行,所以从130执行,再跳转到133行,弹栈后通过iret返回,由于上次为在226行触发中断,所以回到226行。
然后大概率在此行,再次遇到时间中断,从125行开始进行转换,首先将1写入寄存器eax,然后判断,因为此时任务号为0,所以不执行127行,执行128行,则将任务号改为1,然后在129行跳转到任务1。由于任务1上次执行至
132行,所以从133行开始,到iret返回至232行。
又大概率在232行遇到时钟中断,执行到126行比较后跳转到131行,将任务号变为0,回到任务0的代码段。
至此为一个流程。