全球主机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 65|回复: 0

香港服务器Linux系统下如何进行进程切换?(锐讯网络罗沛亮)

[复制链接]
发表于 2017-4-15 15:17:35 | 显示全部楼层 |阅读模式
香港服务器Linux系统下如何进行进程切换?
香港服务器Linux切换并没有使用X86CPU的切换方法,Linux切换的实质就是cr3切换(内存空间切换,在switch_mm函数中)+ 寄存器切换(包括EIP,ESP等,均在switch_to函数中)。这里老罗给您讲述下switch_to主流程:

1、 在switch_mm函数中将new_task->pgd设置到cr3寄存器中,实现页表切换,由于每个进程3-4G的页表映射机制完全一样(从内核页表中直接复制过来的),故这里虽然切换了pgd,但是并无影响,只是在任务回到用户空 间中时,才会发生变化,因为每个任务在0-3G中的页表映射都是各自独立的;
2、 压入esi edi ebp到cur_task堆栈中;
3、 将esp寄存器中的值保存到cur_task.task_struct.thread.esp中,也就是将cur_task切换时的堆栈指针保存起来;
4、将new_task.task_struct.thread.esp中的值设置到esp寄存器中,这里的new_task.task_struct.thread.esp中的值就是new_task上一次被换出时的堆栈指针,现在被恢复了,2和3结合实现了从cur_task到new_task的堆栈切换;
5、将1f地址设置到cur_task.task_struct.thread.eip中,当下次cur_task恢复运行时,将会从1f处开始运行,下面阐述了这种原理;
6、将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中;
7、随后CPU跳转到__switch_to函数中开始执行,注意这里使用的是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处继续执行;
8、此时已经在new_task的执行环境中了,pop ebp, pop edi, popesi,回到schedule函数中,当返回用户空间中时,由于new_task用户空间的eip,ss,esp等均被从new_task的堆栈中弹出到对应寄存器中,从而new_task得以顺利执行。
更多服务器知识,欢迎联系锐讯网络罗沛亮 ,企业QQ:2880269198

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|小黑屋|全球服务器论坛

GMT+8, 2024-5-16 10:16 , Processed in 1.653602 second(s), 19 queries , File On.

Powered by Discuz! X3.5

Copyright © 2001-2024 Tencent Cloud.

快速回复 返回顶部 返回列表