周知生 發表於 2023-11-7 00:00:00

Linux进程基础教程详解

<p>
        计算机实际上可以做的事情实质上非常简单,比如计算两个数的和,再比如在内存中寻找到某个地址等等。这些最基础的计算机动作被称为指令 (instruction)。所谓的程序(program),就是这样一系列指令的所构成的集合。通过程序,我们可以让计算机完成复杂的操作。程序大多数时候被存储为可执行的文件。这样一个可执行文件就像是一个菜谱,计算机可以按照菜谱作出可口的饭菜。</p>
<p>
        那么,<strong>程序和进程(process)的区别又是什么呢?</strong></p>
<p>
        进程是程序的一个具体实现。只有食谱没什么用,我们总要按照食谱的指点真正一步步实行,才能做出菜肴。进程是执行程序的过程,类似于按照食谱,真正去做菜的过程。同一个程序可以执行多次,每次都可以在内存中开辟独立的空间来装载,从而产生多个进程。不同的进程还可以拥有各自独立的IO接口。</p>
<p>
        操作系统的一个重要功能就是为进程提供方便,比如说为进程分配内存空间,管理进程的相关信息等等,就好像是为我们准备好了一个精美的厨房。</p>
<p>
        <strong>看一眼进程</strong></p>
<p>
        首先,我们可以使用$ps命令来查询正在运行的进程,比如$ps -eo pid,comm,cmd,下图为执行结果:</p>
<p>
        (-e表示列出全部进程,-o pid,comm,cmd表示我们需要PID,COMMAND,CMD信息)</p>
<p>
        <img title="Linux进程基础教程详解" alt="Linux进程基础教程详解" id="theimg" src="https://zhuji.jb51.net/uploads/img/202305/556b02ec76f8adb45b9c82e55dad293d.jpg"></p>
<p>
         每一行代表了一个进程。每一行又分为三列。第一列<span>PID</span>(process IDentity)是一个整数,每一个进程都有一个唯一的PID来代表自己的<span>身份</span>,进程也可以根据PID来识别其他的进程。第二列COMMAND是这个进程的简称。第三列CMD是<span>进程所对应的程序</span>以及运行时所带的参数。</p>
<p>
        (第三列有一些由中括号[]括起来的。它们是内核的一部分功能,被打扮成进程的样子以方便操作系统管理。我们不必考虑它们。)</p>
<p>
        我们看第一行,PID为1,名字为init。这个进程是执行/bin/init这一文件(程序)生成的。当Linux启动的时候,init是系统创建的第一个进程,这一进程会一直存在,直到我们关闭计算机。这一进程有特殊的重要性,我们会不断提到它。</p>
<p>
        <strong>如何创建一个进程</strong></p>
<p>
        实际上,当计算机开机的时候,内核(kernel)只建立了一个init进程。Linux内核并不提供直接建立新进程的系统调用。剩下的所有进程都是init进程通过fork机制建立的。新的进程要通过老的进程复制自身得到,这就是fork。fork是一个系统调用。进程存活于内存中。每个进程都在内存中分配有属于自己的一片空间 (address space)。当进程fork的时候,Linux在内存中开辟出一片新的内存空间给新的进程,并将老的进程空间中的内容复制到新的空间中,此后两个进程同时运行。</p>
<p>
        老进程成为新进程的父进程(parent process),而相应的,新进程就是老的进程的子进程(child process)。一个进程除了有一个PID之外,还会有一个PPID(parent PID)来存储的父进程PID。如果我们循着PPID不断向上追溯的话,总会发现其源头是init进程。所以说,所有的进程也构成一个以init为根的树状结构。</p>
<p>
        如下,我们查询当前shell下的进程:</p>
<div class="jb51code">
        <div>
                <div class="syntaxhighlighterbash" id="highlighter_569320">
                        <div class="toolbar">
                                <span>?</span>
</div>
                        <table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
                                                        <div class="line number1 index0 alt2">
                                                                1</div>
                                                        <div class="line number2 index1 alt1">
                                                                2</div>
                                                        <div class="line number3 index2 alt2">
                                                                3</div>
                                                        <div class="line number4 index3 alt1">
                                                                4</div>
                                                        <div class="line number5 index4 alt2">
                                                                5</div>
                                                </td>
                                                <td class="code">
                                                        <div class="container">
                                                                <div class="line number1 index0 alt2">
                                                                        <code class="bash plain">root@vamei:~</code><code class="bash comments"># ps -o pid,ppid,cmd</code>
</div>
                                                                <div class="line number2 index1 alt1">
                                                                        <code class="bash spaces"> </code><code class="bash plain">PID PPID CMD</code>
</div>
                                                                <div class="line number3 index2 alt2">
                                                                        <code class="bash plain">16935 3101 </code><code class="bash functions">sudo</code> <code class="bash plain">-i</code>
</div>
                                                                <div class="line number4 index3 alt1">
                                                                        <code class="bash plain">16939 16935 -</code><code class="bash functions">bash</code>
</div>
                                                                <div class="line number5 index4 alt2">
                                                                        <code class="bash plain">23774 16939 </code><code class="bash functions">ps</code> <code class="bash plain">-o pid,ppid,cmd</code>
</div>
                                                        </div>
                                                </td>
                                        </tr></tbody></table>
</div>
        </div>
        <div class="codetool" id="codetool">
                <div class="code_n">
                        <textarea></textarea>
</div>
        </div>
</div>
<p>
        我们可以看到,第二个进程bash是第一个进程sudo的子进程,而第三个进程ps是第二个进程的子进程。 </p>
<p>
        还可以用$pstree命令来显示整个<span>进程树</span>:</p>
<div class="jb51code">
        <div>
                <div class="syntaxhighlighterbash" id="highlighter_13487">
                        <div class="toolbar">
                                <span>?</span>
</div>
                        <table border="0" cellpadding="0" cellspacing="0"><tbody><tr>
<td class="gutter">
                                                        <div class="line number1 index0 alt2">
                                                                1</div>
                                                        <div class="line number2 index1 alt1">
                                                                2</div>
                                                        <div class="line number3 index2 alt2">
                                                                3</div>
                                                        <div class="line number4 index3 alt1">
                                                                4</div>
                                                        <div class="line number5 index4 alt2">
                                                                5</div>
                                                        <div class="line number6 index5 alt1">
                                                                6</div>
                                                        <div class="line number7 index6 alt2">
                                                                7</div>
                                                        <div class="line number8 index7 alt1">
                                                                8</div>
                                                        <div class="line number9 index8 alt2">
                                                                9</div>
                                                        <div class="line number10 index9 alt1">
                                                                10</div>
                                                        <div class="line number11 index10 alt2">
                                                                11</div>
                                                        <div class="line number12 index11 alt1">
                                                                12</div>
                                                        <div class="line number13 index12 alt2">
                                                                13</div>
                                                        <div class="line number14 index13 alt1">
                                                                14</div>
                                                        <div class="line number15 index14 alt2">
                                                                15</div>
                                                        <div class="line number16 index15 alt1">
                                                                16</div>
                                                        <div class="line number17 index16 alt2">
                                                                17</div>
                                                        <div class="line number18 index17 alt1">
                                                                18</div>
                                                        <div class="line number19 index18 alt2">
                                                                19</div>
                                                        <div class="line number20 index19 alt1">
                                                                20</div>
                                                        <div class="line number21 index20 alt2">
                                                                21</div>
                                                        <div class="line number22 index21 alt1">
                                                                22</div>
                                                        <div class="line number23 index22 alt2">
                                                                23</div>
                                                        <div class="line number24 index23 alt1">
                                                                24</div>
                                                        <div class="line number25 index24 alt2">
                                                                25</div>
                                                        <div class="line number26 index25 alt1">
                                                                26</div>
                                                        <div class="line number27 index26 alt2">
                                                                27</div>
                                                        <div class="line number28 index27 alt1">
                                                                28</div>
                                                </td>
                                                <td class="code">
                                                        <div class="container">
                                                                <div class="line number1 index0 alt2">
                                                                        <code class="bash plain">init─┬─NetworkManager─┬─dhclient</code>
</div>
                                                                <div class="line number2 index1 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">│    └─2*[{NetworkManager}]</code>
</div>
                                                                <div class="line number3 index2 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─accounts-daemon───{accounts-daemon}</code>
</div>
                                                                <div class="line number4 index3 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─acpid</code>
</div>
                                                                <div class="line number5 index4 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─apache2─┬─apache2</code>
</div>
                                                                <div class="line number6 index5 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">│   └─2*]</code>
</div>
                                                                <div class="line number7 index6 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─at-spi-bus-laun───2*[{at-spi-bus-laun}]</code>
</div>
                                                                <div class="line number8 index7 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─atd</code>
</div>
                                                                <div class="line number9 index8 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─avahi-daemon───avahi-daemon</code>
</div>
                                                                <div class="line number10 index9 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─bluetoothd</code>
</div>
                                                                <div class="line number11 index10 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─colord───2*[{colord}]</code>
</div>
                                                                <div class="line number12 index11 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─console-kit-dae───64*[{console-kit-dae}]</code>
</div>
                                                                <div class="line number13 index12 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─</code><code class="bash functions">cron</code>
</div>
                                                                <div class="line number14 index13 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─cupsd───2*</code>
</div>
                                                                <div class="line number15 index14 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─2*</code>
</div>
                                                                <div class="line number16 index15 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─dbus-launch</code>
</div>
                                                                <div class="line number17 index16 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─dconf-service───2*[{dconf-service}]</code>
</div>
                                                                <div class="line number18 index17 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─dropbox───15*[{dropbox}]</code>
</div>
                                                                <div class="line number19 index18 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─firefox───27*[{firefox}]</code>
</div>
                                                                <div class="line number20 index19 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─gconfd-2</code>
</div>
                                                                <div class="line number21 index20 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─geoclue-master</code>
</div>
                                                                <div class="line number22 index21 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─6*</code>
</div>
                                                                <div class="line number23 index22 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─gnome-keyring-d───7*[{gnome-keyring-d}]</code>
</div>
                                                                <div class="line number24 index23 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">├─gnome-terminal─┬─</code><code class="bash functions">bash</code>
</div>
                                                                <div class="line number25 index24 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">│    ├─</code><code class="bash functions">bash</code><code class="bash plain">───pstree</code>
</div>
                                                                <div class="line number26 index25 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">│    ├─gnome-pty-helpe</code>
</div>
                                                                <div class="line number27 index26 alt2">
                                                                        <code class="bash spaces">  </code><code class="bash plain">│    ├─sh───R───{R}</code>
</div>
                                                                <div class="line number28 index27 alt1">
                                                                        <code class="bash spaces">  </code><code class="bash plain">│    └─3*[{gnome-terminal}]</code>
</div>
                                                        </div>
                                                </td>
                                        </tr></tbody></table>
</div>
        </div>
        <div class="codetool" id="codetool">
                <div class="code_n">
                        <textarea></textarea>
</div>
        </div>
</div>
<p>
        fork通常作为一个函数被调用。这个函数会有<span>两次返回</span>,将子进程的PID返回给父进程,0返回给子进程。实际上,子进程总可以查询自己的PPID来知道自己的父进程是谁,这样,一对父进程和子进程就可以随时查询对方。</p>
<p>
        通常在调用fork函数之后,程序会设计一个if选择结构。当<span>PID等于0</span>时,说明该进程为子进程,那么让它执行某些指令,比如说使用<span>exec</span>库函数(library function)读取另一个程序文件,并在当前的进程空间执行 (这实际上是我们使用fork的一大目的: 为某一程序创建进程);而当<span>PID为一个正整数</span>时,说明为父进程,则执行另外一些指令。由此,就可以在子进程建立之后,让它执行与父进程不同的功能。</p>
<p>
        <strong>子进程的终结(termination)</strong></p>
<p>
        当子进程终结时,它会通知父进程,并清空自己所占据的内存,并在内核里留下自己的<span>退出信息</span>(exit code,如果顺利运行,为0;如果有错误或异常状况,为&gt;0的整数)。在这个信息里,会解释该进程为什么退出。父进程在得知子进程终结时,有责任对该子进程使用wait系统调用。这个wait函数能从内核中<span>取出子进程的退出信息</span>,并清空该信息在内核中所占据的空间。但是,如果父进程早于子进程终结,子进程就会成为一个<span>孤儿</span>(orphand)进程。孤儿进程会被过继给init进程,init进程也就成了该进程的父进程。init进程负责该子进程终结时调用wait函数。</p>
<p>
        当然,一个糟糕的程序也完全可能造成子进程的<span>退出信息滞留在内核中的状况</span>(父进程不对子进程调用wait函数),这样的情况下,子进程成为<span>僵尸</span>(zombie)进程。当大量僵尸进程积累时,内存空间会被挤占。 </p>
<p>
        <strong>进程与线程(thread)</strong></p>
<p>
        尽管在UNIX中,进程与线程是有联系但不同的两个东西,但在Linux中,线程只是一种特殊的进程。多个线程之间可以共享内存空间和IO接口。所以,进程是Linux程序的唯一的实现方式。</p>
<p>
        <strong>总结</strong></p>
<p>
        程序,进程,PID,内存空间</p>
<p>
        子进程,父进程,PPID,fork,wait</p>
<p>
        以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。</p>
<p>
        原文链接:http://www.cnblogs.com/vamei/archive/2012/09/20/2694466.html</p>
頁: [1]
查看完整版本: Linux进程基础教程详解