- 论坛徽章:
- 17
|
这个问题我以前思考过,发出来望大家指教:
5. swtich_to(prev, next, last)宏与函数schedule()切换进程:
1). prev为将要换出的进程描述符的地址,而当切换进程后prev进程恢复执行,prev被复用为last
2). next为将要切换至的进程描述符的地址
3). 均为prev进程的schedule()函数的局部变量
movl prev, %eax // prev保存在eax,即(%eax)代表prev->
movl next, %edx // next保存在edx,即(%edx)代表next->
pushfl // 在prev的内核栈上保存了prev进程的eflags寄存器的值
pushl %ebp // 在prev的内核栈上保存了prev进程的ebp寄存器的值
movl %esp,484(%eax) // 将prev进程的esp寄存器值保存在了prev->thread.esp域(484为该域的offset)
movl 484(%edx), %esp // 将next->thread.esp域装载入了esp寄存器,从现在开始push,pop使用的将是next进程的内核栈
movl $1f, 480(%eax) // 将下次prev进程恢复执行的指令位置(prev->thread.eip域,480为该域offset)设置为标号1位置,请注意和下面2条指令对比起来思考
pushl 480(%edx) // 将next进程恢复执行的指令位置(next->thread.eip域)压入next进程的内核栈
jmp _ _switch_to // 直接跳转到__switch_to函数,请注意该函数返回时,返回地址为刚push的next->thread.eip,
// 即返回后就恢复next进程的执行(绝大多数是标号1位置),即next进程被切换时保存的恢复执行位置
1:
popl %ebp // 这里即是prev以后恢复执行的起始位置,也是(绝大部分情况)next进程从__switch_to函数返回后的位置.开始恢复以前压入的ebp
popfl // 恢复eflags寄存器,请注意看第3,4条指令,是保存与恢复的对应
movl %eax,last // 将eax的值即prev保存到last
// 针对最后条指令进行特别说明:此时运行的是next进程,典型的为在schedule()函数中
// 局部变量prev与next(next进程中schedule()函数中的局部变量,为区分,暂且叫做prev_1与next_1)和prev,next将不是同一组值
// 而是以前保存在next进程中的内核栈中的局部变量,现在为了和刚切换出的进程即prev相联系,将prev_1的值更新为prev(eax寄存器的值)
// 即最后指令中的movl %eax,last中的last,由于schedule()函数中复用prev_1局部变量,因此switch_to宏将prev输出到了prev_1
// 也就是说last是prev_1.(所以在汇编指令中看到的应该是movl %eax,prev_1) |
|