<ins id='rcej5'></ins>
  • <i id='rcej5'></i>

      <span id='rcej5'></span>

      <acronym id='rcej5'><em id='rcej5'></em><td id='rcej5'><div id='rcej5'></div></td></acronym><address id='rcej5'><big id='rcej5'><big id='rcej5'></big><legend id='rcej5'></legend></big></address>

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

        <code id='rcej5'><strong id='rcej5'></strong></code>

      1. <i id='rcej5'><div id='rcej5'><ins id='rcej5'></ins></div></i>
          <fieldset id='rcej5'></fieldset>

            <dl id='rcej5'></dl>

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

            • 时间:
            • 浏览:12
            • 来源: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情况中所起的后台正在运行或者被挂起的使命信息  。