<fieldset id='ggws9'></fieldset>

    1. <tr id='ggws9'><strong id='ggws9'></strong><small id='ggws9'></small><button id='ggws9'></button><li id='ggws9'><noscript id='ggws9'><big id='ggws9'></big><dt id='ggws9'></dt></noscript></li></tr><ol id='ggws9'><table id='ggws9'><blockquote id='ggws9'><tbody id='ggws9'></tbody></blockquote></table></ol><u id='ggws9'></u><kbd id='ggws9'><kbd id='ggws9'></kbd></kbd>

        <code id='ggws9'><strong id='ggws9'></strong></code>
        <span id='ggws9'></span>
          <i id='ggws9'><div id='ggws9'><ins id='ggws9'></ins></div></i>
        1. <acronym id='ggws9'><em id='ggws9'></em><td id='ggws9'><div id='ggws9'></div></td></acronym><address id='ggws9'><big id='ggws9'><big id='ggws9'></big><legend id='ggws9'></legend></big></address>
        2. <dl id='ggws9'></dl>
          <ins id='ggws9'></ins>
          <i id='ggws9'></i>

          深入解析Linux系统下的进程切换

          • 时间:
          • 浏览:14
          • 来源:124软件资讯网

              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得以顺遂执行  。

              Linux 前后台历程切换

              当你用shell启动一个法式时  ,往往他是在前台事情的  。 例如经常用PUTTY毗连到远程服务器执行剧本的时间  ,若是当地网络中止后  ,这个时间前台历程就竣事了  ,比力的懊恼  ,必须重新执行  。因此有须要举行前后台历程的切换  。

              例如直接在终端里输入firefox  ,那么会打开firefox ,但当你关闭此终端或者ctrl+c强制终止时  ,firefox也随机关闭了  。

              你可以在执行时后面加一个&  ,这样就在后台事情了  。Shell支持作用控制  ,有以下下令:

              (1). command &让历程在后台运行

              (2). jobs –l 检察后台运行的历程

              (3). fg %n 让后台运行的历程n到前台来

              (4). bg %n 让历程n到后台去;

              PS:"n"为jobs检察到的历程编号  。

              1、执行下令&切换至后台

              在Linux终端运行下令的时间  ,在下令末尾加上&符号  ,就可以让法式在后台运行

              代码如下:

              root@Ubuntu$ ./tcpserv01&

              2、切换正在运行的法式到后台

              若是法式正在前台运行  ,可以使用Ctrl+z 选项把法式暂停  ,然后用 bg %[number]下令把这个法式放到后台运行  ,这个步骤分为3步  ,如下:

              2.1暂停法式运行CTRL+Z

              ctrl + z跟系统使命有关的  ,ctrl + z可以将一个正在前台执行的下令放到后台  ,而且暂停 。

              代码如下:

              [Oracle@linuxidc ~]$ sh ins.sh

              [1]+Stopped ins.sh

              2.2检察暂停的法式

              察看jobs使用jobs或ps下令可以察看正在执行的jobs  。

              代码如下:

              [oracle@linuxidc ~]$ jobs -l

              [1]+ 4524Stopped ins.sh

              jobs下令执行的效果  ,+表现是一个当前的作业  ,减号表是是当前作业之后的一个作业  。

              jobs -l选项可显示所有使命的PID ,jobs的状态可以是running , stopped ,Terminated

              2.3切换法式至后台

              bg将一个在后台暂停的下令 ,酿成继续执行若是后台中有多个下令 ,可以用bg %jobnumber将选中的下令调出.

              代码如下:

              [oracle@linuxidc ~]$ bg %1

              [oracle@linuxidc ~]$ jobs -l

              [1]+ 4524Running ins.sh

              2.4切换法式至前台

              也可以用 fg %[number]指令把一个法式掉到前台运行

              代码如下:

              [oracle@linuxidc ~]$ fg %1

              ./tcpserv01

              2.5终止后台法式

              也可以直接终止后台运行的法式 ,使用 kill 下令

              代码如下:

              [oracle@linuxidc ~]$ kill %1

              可是若是使命被终止了(kill) ,shell 从当前的shell情况已知的列表中删除使命的历程标识;也就是说  ,jobs下令显示的是当前shell情况中所起的后台正在运行或者被挂起的使命信息 。