7.5 任务切换(Task Switching)
以下情况中,80386切换到另一个任务执行:
1、 当前任务执行了一个JMP或CALL,而操作数中指定了一个TSS描述符。
2、 当前任务执行了一个JMP或CALL,而操作数中指定了一个任务门。
3、 一个在IDT中的中断向量或异常向量导致向一个新的任务切换。
4、 当前任务执行了一条IRET指令,而且NT位设置时。
JMP, CALL, IRET, 中断和异常原先被设计用于在同一个任务内的机制,不需要任务切换。访问到何种类型的描述符还是在标志字段NT(nested taks)位可以用于区分出标标准的机制还是变种的任务切换机制。
为了引起任务切换,JMP或CALL指令可以指定一个TSS描述符或者一个任务门。两种情况下作用是相同的:80386切换到指定的任务。
当在IDT中的中断或异常向量指示了一个任务门时,中断或异常将引起任务切换。如果指示了一个IDT中的中断门或陷阱门,不发生任务切换。关于中断的更多信息,请参看第9章。
当以一个任务或一个中断子程序来引发时,中断处理程序总是将控制返回到被中断任务的子程序。如果NT位被置位,中断处理程序则是一个中断任务,IRET指令将返回到被中断的子程序。
任务切换操作将做以下的步骤:
1、 检测当前任务有权切换到指定的任务。这时数据访问规则将用于检测JMP或CALL指令。TSS描述符或者任务门的DPL字段必须小于或者等于CPL和门选择子RPL字段的最大值。中断、异常、IRET指令可以切换到任何任务,而不必管目标TSS描述符或者目标任务门的DPL字段。
2、 检测目标TSS描述符存在的,而且有一个有效的界限值。到这时,所有的错误都算是在的引发任务切换(outgoing task)的上下文中发生的。错误是可以被处理和重起的,且对于应用程序是透明的。
3、 保存当前任务的状态。处理器从任务寄存器中缓存的不可见部分来找到当前任务的基址。处理器拷贝寄存器值到当前任务TSS(EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, ES, CS, SS, DS, FS, GS, 和 标志寄存器EFLAG)。EIP字段则指向引起任务切换的指令的下一条指令。
4、 将新的任务的选择子加载到任务寄存器,将新任务的TSS描述符设置为忙。设置MSW的TS(task switched)标志位。选择子或是从指令操作数中得到,或是从任务门中得到。
5、 从新的任务的TSS中加载任务的状态,并恢复其执行。加载的寄存器是LDT寄存器,标志寄存器(EFLAG)通用寄存器EIP,EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI;段寄存器ES,CS,SS,DS,FS,和GS。还有PDBR(CR3)。所有检测到的错误将发生在新任务的上下文中。对于一个异常处理程序,看来起好似新任务的第一条指令还未执行。
注意,不管怎么样,旧任务的状态总是会被保存。如果这个任务被重新执行,它执行引起任务切换的指令的后一条指令。当任务执行时,所有寄存器的值将被恢复。
每一次任务切换都会设置MSW(machine status word)的TS(task switched)位。TS标志对于有协处理器的系统来说是很重要的。TS位指出了协处理器的状态可能和当前任务的状态不一致了。第11章进一步讨论TS位。
处理任务切换异常的处理程序(表7-1中由第4到16引起的异常)应该注意加载引起异常的选择子的操作。这样的操作可能引发第二次异常,除非异常处理程序首先检查了选择子并修定了潜在的问题。
将要执行的任务的特权级即不被引起任务切换的任务所影响,也不会被它所约束。因为每个任务的地址空间是分开的,且有不同的TSS,还有就是特权级规则可以用于防止不合法的TSS访问,但是没有哪种特权级规则需要用来去约束不同任务间的CPL。新的任务将在CS选择子的RPL字段特权级执行,这个CS是由TSS中加载的。