对linux0.00的timer_interrupt进行注释。关注任务切换。(转)
/* Timer interrupt handler 通过中断门进入这个处理函数时,中断标志IF=0,不允许再中断进来.*/
.align 2
timer_interrupt:
push %ds
pushl %eax
movl $0x10, %eax
mov %ax, %ds
movb $0x20, %al
outb %al, $0x20
movl $1, %eax
cmpl %eax, current
je 1f
movl %eax, current
ljmp $TSS1_SEL, $0 /*ljmp是编译器的伪指令,反汇编后实际是: jmp 0030:00000000*/
jmp 2f
1: movl $0, current
ljmp $TSS0_SEL, $0 /*即: jmp 0020:00000000*/
2: popl %eax /* 有个疑问? jmp到TSS段后,后面这个pop还执行吗? 这个中断处理能完成到iret吗?
为何要在中断里面跳转到不同的任务? 如果说jmp后新任务的寄存器已被装到CPU了,
那么这里还pop,会不会覆盖了CPU中针对新任务的寄存器值?
用bochs调试看看结果.
答: 这就是理解任务切换的关键地方. 当task0执行了jmp 30:0后,任务就切换到task1了,
一切与task0无关了,但是task0已经把紧接着的下一条要执行的指令(jmp 2f)地址保存到
TSS0区域的EIP的地方了. 当新任务task1在执行时,CPU的环境全是它的,包括IF开中断标志
也是打开的,即在task1的环境下还允许timer中断发生,然后再次执行任务切换,再切换回
task0执行,这时候原来的task0接着从jmp 2f的地方开始执行,然后pop,然后中断返回到
task0中的代码去,继续完成它的打印'A'的任务. 从宏观上来看,task0对task1什么也感觉
不到,就好象整个CPU全部都是task0的,只不过一会儿一个timer中断,中断处理完了,再回到
自己的代码上继续打印.
换一个角度来看,task1也是这种感觉. 那么整体来看,就好象task0有一个独立的CPU,task1
也有一个独立的CPU,大家各忙各的,互不干扰. (实际充分利用了一颗物理CPU,别闲着)*/
pop %ds
iret /*中断返回后恢复IF标志*/
浙公网安备 33010602011771号