打开APP
未登录
开通VIP,畅享免费电子书等14项超值服
开通VIP
首页
好书
留言交流
下载APP
联系客服
switch_to
Liucw2012
>《进程管理及调度》
2012.04.26
关注
switch_to
分类:
Process Scheduling
2007-01-10 12:17
1257人阅读
评论
(2)
收藏
举报
switch_to()负责从上一个进程的处理器状态切换到新进程的处理器状态
15
#define
switch_to(prev,next,last) do {
16
unsigned
long
esi,edi;
17
asm
volatile
(
"
pushfl
"
18
"
pushl %%ebp
"
19
"
movl %%esp,%0
"
/*
save ESP
*/
20
"
movl %5,%%esp
"
/*
restore ESP
*/
21
"
movl $1f,%1
"
/*
save EIP
*/
22
"
pushl %6
"
/*
restore EIP
*/
23
"
jmp
__switch_to
"
24
"
1:
"
25 "
popl %%ebp
"
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个参数,表明这段程序执行后有5项数据会有改变。其中%0和%1都在内存中,分别为
prev->thread.esp和
prev->thread.eip,而%2则与寄存器EAX结合,对应于参数中的last.
[
输出的参数为5个,分别为prev->thraad.esp(%0), prev->thread.eip(%1), last(%2), esi(%3), edi(%4) ]
输入部分有4个参数。其中%5和%6在内存中,分别为
next->thread.esp和
next->thread.eip;%7与寄存器EAX结合,对应于prev;%8与寄存器EDX结合,对应于next [
输入的参数为4个,分别为next->thread.esp(%5), next->thread.eip(%6), prev(%2), next(%7) ]
"2" (prev), "d" (next)
,
在寄存器%%eax和%%edx中分别保存prev和next的值
第一步,
pushfl, pushl %%ebp
, 将进程prev的eflags和ebp保存到该进程的内核堆栈中
第二步,
movl %%esp, %0(prev->thread.esp)
,将当前进程prev的系统空间堆栈指针存入该进程的进程描述符结构体中(prev->thread.esp).
第三步,movl %5(next->thread.esp), %%esp 将下一个待执行进程next的系统空间堆栈指针切换进来.由于硬件相关的进程上下文信息都跟内核堆栈相关,所以第二步和第三步可以说完成了进程切换的大部分工作.(从21行开始就在使用进程next的堆栈了。换言之,从21开始,“当前进程”已经是next而不是prev了)
第四步,movl $1f, %1(prev->thread.eip), 将25行的地址保存在prev->thread.eip中
第五步,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 恢复新进程的相关寄存器的值.由于在第三步中,进程栈切换已经完成,所以,这里是对新的进程栈的恢复操作.
注:
current与ESP的关系
在内核代码中当需要访问当前进程的task_struct结构时使用的指针current实际上是个宏定义,它是根据当前进程的堆栈指针ESP计算出来的
eip是下条要执行的指令地址
ebp指向内核堆栈基地址
esp指向内核堆栈栈顶
第一步
pushfl
pushl %%ebp
进程prev的内核堆栈
| |
| |
|-----------|
| eflags |
| ebp |
%%esp-->| |
第二步
movl %%esp,%0 //prev->thraad.esp(%0)
进程prev的内核堆栈
| |
| |
|-----------|
| eflags |
(%%esp) | ebp |
prev->thread.esp-->| |
第三步
movl %5,%%esp //next->thread.esp(%5)
进程next的内核堆栈
| |
| |
| |
| eflags |
| ebp |
%%esp-->| |
(next->thread.esp)
第四步
movl $1f,%1 //prev->thread.eip(%1)
prev->thread.eip = (第25行的地址)
作为进程prev下一次被调度运行时的“返回地址”
第五步
pushl %6 //next->thread.eip(%6)
进程next的内核堆栈
| |
| |
| |
|eflags |
|ebp |
|next->thread.eip|
%%esp-->| |
将next->thread.eip压入堆栈(
next的内核堆栈?
):这里的next->thread.eip正是
进程next上一次被调离时在第21行中保存的。它也执行这里的标号"1", 即25行的popl指令
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报
。
打开APP,阅读全文并永久保存
查看更多类似文章
猜你喜欢
类似文章
【热】
打开小程序,算一算2024你的财运
《深入理解Linux内核3rd》学习笔记——进程切换(下):switch
linux内核进程切换代码分析
7.switch
Linux进程切换与进程调度时机 | Chaos
C语言函数调用栈(一)
对gcc编译汇编码解析
更多类似文章 >>
生活服务
热点新闻
留言交流
回顶部
联系我们
分享
收藏
点击这里,查看已保存的文章
导长图
关注
一键复制
下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!
联系客服
微信登录中...
请勿关闭此页面
先别划走!
送你5元优惠券,购买VIP限时立减!
5
元
优惠券
优惠券还有
10:00
过期
马上使用
×