linux进程如何切换,Linux进程切换分析

在switch_mm函数中将new_task->pgd设置到cr3寄存器中,实现页表切换,由于每个进程3- 4G的页表映射机制完全一样(从内核页表中直接复制过来的),故这里虽然切换了pgd,但是并无影响,只是在任务回到用户空 间中时,才会发生变化,因为每个任务在0-3G中的页表映射都是各自独立的;

压入esi edi ebp到cur_task堆栈中;

将esp寄存器中的值保存到cur_task.task_struct.thread.esp中,也就是将cur_task切换时的堆栈指针保存起来;

将new_task.task_struct.thread.esp 中的值设置到esp寄存器中,这里的new_task.task_struct.thread.esp中的值就是new_task上一次被换出时的堆栈指 针,现在被恢复了,2和3结合实现了从cur_task到new_task的堆栈切换;

将1f地址设置到cur_task.task_struct.thread.eip中,当下次cur_task恢复运行时,将会从1f处开始运行,下面阐述了这种原理;

将new_task.task_struct.thread.eip 压入到new_task的堆栈中,这里new_task.task_struct.thread.eip的值就是1f,因为从4中可知,new_task 上一次被换出时,其也是和现在的cur_task类似,1f地址被设置到new_task.task_struct.thread.eip中;

随 后CPU跳转到__switch_to函数(注意,在__switch_to中,做了一件非常重要的事情就是让init_tss.esp0= new_task.task_struct.esp0,原因见【C.Linux进程:Linux进程管理和X86进程管理的结合】一文)中开始执行,注意 这里使用的是jmp,不是call,call会pusheip,而jmp不会,由于__switch_to是函数,当CPU执行完该函数后,最后一条指令 必然为iret,该指令会popeip,从5中可以知道,此时new_task堆栈中的镜像为[......., esi,edi,ebp,eip(&1f)],故popeip将值eip(&1f)设置到eip寄存器中,这样当iret执行完毕后, CPU将从eip处继续执行,也就是从1f处继续执行;;

此时已经在new_task的执行环境中了,pop ebp, pop edi, popesi,回到schedule函数中,当返回用户空间中时,由于new_task用户空间的eip,ss,esp等均被从new_task的堆栈中 弹出到对应寄存器中,从而new_task得以顺利执行;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值