Skip to content

Commit

Permalink
Deployed aa3deee with MkDocs version: 1.5.3
Browse files Browse the repository at this point in the history
  • Loading branch information
TomSjtu committed Dec 8, 2023
1 parent 640b3bb commit f6d09b0
Show file tree
Hide file tree
Showing 21 changed files with 51 additions and 24 deletions.
2 changes: 1 addition & 1 deletion 404.html
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
2 changes: 1 addition & 1 deletion arm/barrier/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
2 changes: 1 addition & 1 deletion arm/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
2 changes: 1 addition & 1 deletion cloud/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
2 changes: 1 addition & 1 deletion linux/drivers/chardev/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
2 changes: 1 addition & 1 deletion linux/drivers/dts/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
2 changes: 1 addition & 1 deletion linux/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
2 changes: 1 addition & 1 deletion linux/kernel/interrupt/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
2 changes: 1 addition & 1 deletion linux/kernel/others/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
35 changes: 31 additions & 4 deletions linux/kernel/sched/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@



<title>进程调度 - 一只Tom的笔记本</title>
<title>进程管理与调度 - 一只Tom的笔记本</title>



Expand Down Expand Up @@ -107,7 +107,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">

进程调度
进程管理与调度

</span>
</div>
Expand Down Expand Up @@ -519,7 +519,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down Expand Up @@ -1065,7 +1065,34 @@



<h1 id="_1">进程调度<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h1>
<h1 id="_1">进程管理与调度<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h1>
<p>进程就是处于执行期的程序,当我们将代码编译成可执行文件时,输入./a.out,我们就开启了一个新的进程。进程从磁盘加载到内存的过程请参考<a href="../../../others/ld/">程序的装载</a></p>
<p>一个进程相当于一个大型的项目组,这个项目组包含着许多资源,比如打开的文件信息,占用的内存空间,处理器的状态等。而线程就是项目组中执行具体任务的人。就像一个项目组至少得有一个人,一个进程必须得有一个主线程。你可以把所有的任务都交给主线程,但是大部分情况下,我们都会让把一个大的任务拆分成一个个小任务,然后另外开辟线程去处理它们。那么我们是否可以再创建几个进程去处理呢?可以,但是没有必要。首先,进程占用的资源空间很大,而线程是轻量级的,创建的速度非常快。其次,进程之间共享资源非常麻烦,而线程由于是同一个进程下的,他们可以共同访问某些资源。这就好比一个公司下面不同项目组之间交接工作容易扯皮,但是如果大家都在同一个项目组下相对来说就好很多。</p>
<p>在Linux系统下,线程与进程并不特别区分。他们同是一个task_struct结构体,内核在管理和调度的时候,不会管你是进程还是线程,一视同仁。</p>
<p>Linux系统通过<em>fork()</em>系统调用创建一个进程,调用fork()的进程称为父进程,新产生的进程称为子进程。fork()函数返回两次,如果是0则是子进程;如果大于0则是父进程。这里给了一段示例代码,你先有个概念,具体内核是如何创建进程的我们后面再讲。</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdio.h&gt;</span>
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdlib.h&gt;</span>
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;unistd.h&gt;</span>
<a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a>
<a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a><span class="w"> </span><span class="kt">pid_t</span><span class="w"> </span><span class="n">pid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fork</span><span class="p">();</span>
<a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a>
<a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pid</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a><span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">&quot;子进程,进程ID:%d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="w"> </span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pid</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-0-12" name="__codelineno-0-12" href="#__codelineno-0-12"></a><span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">&quot;父进程,进程ID:%d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">getpid</span><span class="p">());</span>
<a id="__codelineno-0-13" name="__codelineno-0-13" href="#__codelineno-0-13"></a><span class="w"> </span><span class="n">wait</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
<a id="__codelineno-0-14" name="__codelineno-0-14" href="#__codelineno-0-14"></a><span class="w"> </span><span class="n">printf</span><span class="p">(</span><span class="s">&quot;子进程结束。</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<a id="__codelineno-0-15" name="__codelineno-0-15" href="#__codelineno-0-15"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-0-16" name="__codelineno-0-16" href="#__codelineno-0-16"></a><span class="w"> </span><span class="n">perror</span><span class="p">(</span><span class="s">&quot;fork失败&quot;</span><span class="p">);</span>
<a id="__codelineno-0-17" name="__codelineno-0-17" href="#__codelineno-0-17"></a><span class="w"> </span><span class="n">exit</span><span class="p">(</span><span class="n">EXIT_FAILURE</span><span class="p">);</span>
<a id="__codelineno-0-18" name="__codelineno-0-18" href="#__codelineno-0-18"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-0-19" name="__codelineno-0-19" href="#__codelineno-0-19"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<a id="__codelineno-0-20" name="__codelineno-0-20" href="#__codelineno-0-20"></a><span class="p">}</span>
</code></pre></div>
<p>通常,新创建的进程都是为了执行不同的程序,调用<em>exec()</em>可以创建新的地址空间,并把新的程序替换掉当前程序。Linux内核中,fork()底层是由<em>clone()</em>系统调用实现的。子程序通过<em>exit()</em>系统调用退出,进程退出后被设置为僵死(zombie)状态,直到父进程使用<em>wait()</em>或者<em>waitpid()</em>回收子进程的资源。</p>
<p>前面说了,在Linux系统下,不管你是进程还是线程,都统一视作task_struct结构体。这个结构非常复杂,包含了一个进程/线程的所有信息。内核统一将所有task_struct放在一个双向循环列表中管理。</p>



Expand Down
2 changes: 1 addition & 1 deletion linux/kernel/synch/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
2 changes: 1 addition & 1 deletion others/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
10 changes: 5 additions & 5 deletions others/ld/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down Expand Up @@ -1147,7 +1147,7 @@ <h2 id="gcc">gcc编译步骤<a class="headerlink" href="#gcc" title="Permanent l
<h2 id="_2">程序的链接与装载<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h2>
<h3 id="_3">程序的二进制格式<a class="headerlink" href="#_3" title="Permanent link">&para;</a></h3>
<p>经过预处理、编译、汇编以后,.c文件被编译成了.o文件,又叫可重定位文件,这是ELF格式的一种。这个文件格式是这样的。</p>
<p><img alt="ELF文件头" src="../../images/ELF_1.webp" /></p>
<p><img alt="ELF文件头" src="../../images/others/ELF_1.webp" /></p>
<p>其中ELF Header记录一个个section的信息,我们可以使用readelf -h查看一个.o文件的Header信息。这个二进制文件里存放着程序的代码以及变量等等信息。</p>
<p>.text:存放编译好的二进制代码。</p>
<p>.rodata:存放只读数据,比如字符串常量。</p>
Expand All @@ -1159,9 +1159,9 @@ <h3 id="_3">程序的二进制格式<a class="headerlink" href="#_3" title="Perm
<p>这些section的数据信息保存在Section Header Table里。为什么叫可重定位文件,因为编译成.o文件的时候,使用了一些外部函数或者变量,此时并不知道这些函数或变量在内存中的位置,所以需要在.o文件中说明这些符号将来是需要重新定位的。</p>
<h3 id="_4">静态库与动态库<a class="headerlink" href="#_4" title="Permanent link">&para;</a></h3>
<p>我们可以将一个个.o文件打包成库文件的形式,供其他程序调用。形成的二进制格式叫可执行文件,是ELF文件的第二种形式。它的结构如下。</p>
<p><img alt="库文件头" src="../../images/ELF_2.webp" /></p>
<p>这个格式与可重定位文件类似,只不过在链接的过程中,部分section合并了。比如都是二进制代码,那就一起合并到.text段中去。小的section合并成为了大的segment。在ELF头里面,有个叫e_entry的虚拟地址,是程序的入口地址。当静态库与其他程序链接在一起时,会把静态库的信息合并进去,形成一个更大的可执行文件,这样的好处就是该程序就不依赖与静态库文件了。坏处就是有其他需要链接的文件,同样会复制一份信息到内存。而静态库更新后,如果不重新进行编译,程序就无法运行了。所以就有了动态库。动态库也是ELF文件的第三种形式共享对象文件。</p>
<p>当动态库被链接到程序中去时,只保留对动态库的引用,并且一个动态库可以被多个程序引用。而为了在运行时确定函数位置,基于动态库链接的.so文件多了一些信息。首先是一个叫.interp的段,这里面是ld-linux.so,这是动态链接器,运行时的链接动作都是它做的。另外还多了两个section,一个是.plt,过程链接表,一个是.got,全局偏移量表。假设我们有一个函数func()需要重定位,由于代码段是不可写的,所以在链接过程中,无法将其实际地址写入。解决办法是用了一个小技巧,在汇编指令中,当执行到func()函数时,告诉程序你要去PLT[x]位置处去寻找func函数的位置。而PLT[X]又告诉程序你要去GOT[Y]的地方去找函数位置。当第一次执行时,GOT[Y]里的位置信息是空的,于是GOT告诉PLT,我这里没有定位信息。PLT收到这个信息之后,调用PLT[0],PLT[0]转而调用GOT[2],这里面保存的是链接器的入口地址。链接器会找到func函数的入口地址,然后把这个地址写入到GOT[Y]中,下次再调用func函数时,就确定了函数地址</p>
<p><img alt="库文件头" src="../../images/others/ELF_2.webp" /></p>
<p>这个格式与可重定位文件类似,只不过在链接的过程中,部分section合并了。比如都是二进制代码,那就一起合并到.text段中去。小的section合并成为了大的segment。在ELF头里面,有个叫e_entry的虚拟地址,是程序的入口地址。当静态库与其他程序链接在一起时,会把静态库的信息合并进去,形成一个更大的可执行文件,这样的好处就是该程序执行的时候不依赖于静态库文件。坏处就是,有其他需要链接的文件,同样会复制一份信息到内存,造成了空间的浪费。当静态库更新后,如果不重新进行编译,程序就无法运行了。为了解决空间浪费以及程序扩展性差的问题,动态库就出现了。动态库也是ELF文件的第三种形式——<strong>共享对象文件</strong></p>
<p>当动态库被链接到程序中去时,只保留了对动态库的引用,并且一个动态库可以被多个程序引用。而为了在运行时确定函数位置,基于动态库链接的.so文件多了一些信息。首先是一个叫.interp的段,这里面是ld-linux.so,这是动态链接器,运行时的链接动作都是它做的。另外还多了两个section,一个是.plt,过程链接表,一个是.got,全局偏移量表。假设我们有一个函数func()需要重定位,由于代码段是不可写的,所以在链接过程中,无法将其实际地址写入。解决办法是用了一个小技巧,在汇编指令中,当执行到func()函数时,告诉程序你要去PLT[x]位置处去寻找func函数的位置。而PLT[X]又告诉程序你要去GOT[Y]的地方去找函数位置。当第一次执行时,GOT[Y]里的位置信息是空的,于是GOT告诉PLT,我这里没有定位信息。PLT收到这个信息之后,调用PLT[0],PLT[0]转而调用GOT[2],这里面保存的是链接器的入口地址。链接器会找到func函数的入口地址,然后把这个地址写入到GOT[Y]中,那么下次再调用func函数时,就不需要以上这么麻烦的步骤了,因为函数的地址已经写在了GOT表中</p>
<h3 id="_5">程序的装载<a class="headerlink" href="#_5" title="Permanent link">&para;</a></h3>
<p>通过execv系统调用,执行load_elf_binary()函数,将可执行文件装载到内存中。</p>
<p>具体实现细节待定。</p>
Expand Down
2 changes: 1 addition & 1 deletion pl/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down
2 changes: 1 addition & 1 deletion search/search_index.json

Large diffs are not rendered by default.

Binary file modified sitemap.xml.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion tools/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@


<span class="md-ellipsis">
进程调度
进程管理与调度
</span>


Expand Down

0 comments on commit f6d09b0

Please sign in to comment.