linux内核进程切换代码分析
时间:2011-01-05
来源:互联网
- #define switch_to(prev,next,last) do{
-
- asm volatile {"pushl %%esi\n\t"
-
- "pushl %%edi\n\t"
-
- "movl %%esp,%0\n\t"
-
- "movl %3,%%esp\n\t"
-
- "movl $1f,%1\n\t"
-
- "pushl %4\n\t"
-
- "1\t"
-
- "popl %%ebp\n\t"
-
- "popl %%edi\n\t"
-
- "popl %%esi\n\t"
-
- :"m=" (prev->thread.esp),"m" (prev->thread.eip), \
-
- "b"(last)
-
- :"m" (next->thread.esp),"m" (next->thread.eip),
-
- "a"(prev), "d"(next),
-
- "b"(prev));
如图所示,A为此时正运行的进程(prev),B为待切换的进程(next)。切换过程一共分为四步:
第一步:即movl %%esp,%0也就是将寄存器esp中的值保存在进程A的thread.esp中。
第二步:即movl %3,%%esp也就是将进程B的thread.esp的值赋给寄存器esp。(实际上这个值就
是上一次从B中切换走的时候执行的第一步的结果。为了要返回,必须为以后考虑周全。)
第三步:即movl $1f,%1其中1f就是说程序后面标号为1的地方,将标号为1的地方的代码的地址保存
到A的thread.eip中。
第四步:即pushl %4,将进程B的thread.eip的值压栈,此时的esp指向已是进程B的堆栈。(实际上此时的thread.eip就是上一次从B中切换走的时候第三步执行的结果,即标号一得位置。所以任何进程恢复运行,首先肯定是执行的标号1的代码。)
这里要说明的是,pushl %4后面的一句代码是调转jmp __switch_to 而__switch_to是个函数,他执行完成以后会有一个ret的操作,即将栈中的第一个地址作为函数返回的地址,所以就会跳到标号1的地方去执行代码了。
由于__switch_to的代码在schedule()中,而shedule()函数又在其他系统调用函数中,比如sys_exit()中,所以先返回到调用B进程上次切换走时的schedule()中,然后返回到调用schedule()的系统调用函数中,最后系统调用又是在用户空间调用的,所有返回到系统调用的那个地方,接着执行用户空间的代码。这样就彻底的回到了B进程。注意由于此时的返回路径是根据B堆栈中保存的返回地址来返回的,所以肯定会返回到B进程中。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ywf861029/archive/2011/01/05/6117145.aspx
作者: ywf851207 发布时间: 2011-01-05
自己先顶一个

作者: Godbach: 发布时间: 2011-01-05
LZ 博客上很多好文章啊。欢迎多来内核版交流。
作者: ywf851207 发布时间: 2011-01-05
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28