进程切换简述(2.6)
15 #define switch_to(prev,next,last) do {
16 unsigned long esi,edi;
17 asm volatile("pushflnt"
18 "pushl %%ebpnt"
19 "movl %%esp,%0nt" /* save ESP */
20 "movl %5,%%espnt" /* restore ESP */
21 "movl $1f,%1nt" /* save EIP */
22 "pushl %6nt" /* restore EIP */
23 "jmp __switch_ton"
24 "1:t"
25 "popl %%ebpnt"
26 "popfl"
27 :"=m" (prev->thread.esp),"=m" (prev->thread.eip),
28 "=a" (last),"=S" (esi),"=D" (edi)
29 :"m" (next->thread.esp),"m" (next->thread.eip),
30 "2" (prev), "d" (next));
31 } while (0)
输出的参数为5个,分别为prev->thraad.esp(%0), prev->thread.eip(%1), last(%2), esi(%3), edi(%4),
输入的参数为4个,分别为next->thread.esp(%5), next->thread.eip(%6), prev(%2), next(%7)
第一步,pushfl, pushl %%epb, 用于保存prev进程的eflags和ebp.
第二步,movl %%esp, %0(prev->thread.esp),将当前进程的栈指针写入该进程的进程描述符结构中.
第三步,movl %5(next->thread.esp), %%esp 将下一个待执行的进程的栈指针切换进来.由于硬件相关的
进程上下文信息都跟栈相关,所以第二步和第三步可以说完成了进程切换的大部分工作.
第四步,movl $1f, %1(prev->thread.eip), 将25行的地址保存
第五步,pushl %6(next->thread.eip), jmp __switch_to 这是整个宏的玄机所在,首先将next->thread.eip
压栈, 然后跳转到__switch_to()函数中去执行,这里要注意的是,C函数执行完成后,其返回地址在栈顶位置,
又由于现在栈顶的值是next->thread.eip, 这样,next->thread.eip(即上一次它被调离时25行的地址)即为这个
函数的返回地址,这样,函数返回后,将跳转到25行这个地址去执行.
第六步,popl %%ebp, popfl 恢复新进程的相关寄存器的值.由于在第三步中,进程栈切换已经完成,所以,这里
是对新的进程栈的恢复操作.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
thanx, this is just the version 2.6.11.
pushfl在新的代码中砍掉了,理由是它的作用只是IOPL,把IOPL单拿出来处理更加清晰,不妨多解释一下这里,为什么只是IOPL。