Linux内核作业--分析Linux内核创建一个新进程的过程

  1. 说明

    刘玉龙 
    原创作品转载请注明出处 
    《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

  2. 准备工作 
    task_struct的应该会存在哪些结构:
<code class="hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">1、进程状态、将纪录进程在等待、运行、或死锁
2、调度信息、由哪个调度函数调度、怎样调度等
3、进程的通讯状况
4、有插入进程链表的相关操作,因此必须有链表连接指针、当然是task_struct型
5、时间信息,比如计算好执行的时间、以便CPU资源的分配
6、标号,决定改进程归属
7、可以读写打开的一些文件信息
8、进程上下文和内核上下文
9、处理器上下文
10、内存信息等等</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

课堂提供在/linux-3.18.6/include/linux/sched.h中找到tast_struct的定义: 
现在的Linux系统基本上是按照操作系统理论来进行设计的,但是在实现的过程中,理论往往是不够的,为了实现很多实际的需求,tast_struct还定义了很多额外的结构,来方便系统的相关管理,比如后面没有列出来的一些文件操作相关的结构,这些结构一般用于当一个进程没有按照规范来操作文件时,当进程被杀掉后,系统任然可以对这些不规范的操作进行管理。当然,后面还有很多内容也是如此,我们就不一一叙说了,我们只看创建一个进程的相关重点。

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> task_struct {
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">volatile</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> state;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//说明了该进程是否可以执行,还是可中断等信息</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> flags;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程号,在调用fork()时给出</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> sigpending;             <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程上是否有待处理的信号</span>
    mm_segment_t addr_limit;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程地址空间,区分内核进程与普通进程在内存存放的位置不同</span>
                                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//0-0xBFFFFFFF for user-thead</span>
                                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//0-0xFFFFFFFF for kernel-thread</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//调度标志,表示该进程是否需要重新调度,若非0,则当从内核态返回到用户态,会发生调度</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">volatile</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> need_resched;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> lock_depth;             <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//锁深度</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> nice;                  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程的基本时间片</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程的调度策略,有三种,实时进程:SCHED_FIFO,SCHED_RR, 分时进程:SCHED_OTHER</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> policy;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> mm_struct *mm;       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程内存管理信息</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> processor;
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//若进程不在任何CPU上运行, cpus_runnable 的值是0,否则是1 这个值在运行队列被锁时更新</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> cpus_runnable, cpus_allowed;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> list_head run_list;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//指向运行队列的指针</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> sleep_time;   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程的睡眠时间</span>
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//用于将系统中所有的进程连成一个双向循环链表, 其根是init_task</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> task_struct *next_task, *prev_task;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> mm_struct *active_mm;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> list_head local_pages;       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//指向本地页面      </span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> allocation_order, nr_local_pages;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> linux_binfmt *binfmt;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程所运行的可执行文件的格式</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> exit_code, exit_signal;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> pdeath_signal;                  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//父进程终止是向子进程发送的信号</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> personality;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> did_exec:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>; 
    pid_t pid;                          <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程标识符,用来代表一个进程</span>
    pid_t pgrp;                         <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程组标识,表示进程所属的进程组</span>
    pid_t tty_old_pgrp;                 <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程控制终端所在的组标识</span>
    pid_t session;                      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//进程的会话标识</span>
    pid_t tgid;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> leader;                         <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//表示进程是否为会话主管</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> task_struct *p_opptr,*p_pptr,*p_cptr,*p_ysptr,*p_osptr;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> list_head thread_group;      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//线程链表</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> task_struct *pidhash_next;   <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//用于将进程链入HASH表</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> task_struct **pidhash_pprev;
    wait_queue_head_t wait_chldexit;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//供wait4()使用</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> completion *vfork_done;      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//供vfork() 使用</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> rt_priority;          <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//实时优先级,用它计算实时进程调度时的weight值</span>
    …… 
};</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li></ul>

3.进程创建分析 
fork函数到底如何进行对应的内核处理过程sys_clone。

<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <stdio.h></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <stdlib.h></span>
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include <unistd.h></span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> * argv[])
{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> pid;
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* fork another process */</span>
    pid = fork();
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (pid < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) 
    { 
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* error occurred */</span>
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">fprintf</span>(stderr,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Fork Failed!"</span>);
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">exit</span>(-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
    } 
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (pid == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) 
    {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* child process */</span>
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"This is Child Process!\n"</span>);
    } 
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>
    {  
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* parent process  */</span>
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"This is Parent Process!\n"</span>);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* parent will wait for the child to complete*/</span>
        wait(NULL);
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Child Complete!\n"</span>);
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li></ul>
检测题目的最后一个是什么鬼
Linux中,fork()系统调用产生的子进程在系统调用处理过程中从(:ret_from_fork)处开始,我要留着以后看一下,莫名其妙

Linux中,PCB task_struct中不包含哪个信息()? 
进程状态 
进程打开的文件 
进程优先级信息 
进程包含的线程列表信息 
创建一个新进程在内核中的执行过程 
fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建; 
Linux通过复制父进程来创建一个新进程,那么这就给我们理解这一个过程提供一个想象的框架: 
复制一个PCB——task_struct

err = arch_dup_task_struct(tsk, orig);

要给新进程分配一个新的内核堆栈

<code class="hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">ti <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> alloc_thread_info_node(tsk, node);
tsk<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-></span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">stack</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> ti;
setup_thread_stack(tsk, orig); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//这里只是复制thread_info,而非复制内核堆栈</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

要修改复制过来的进程数据,比如pid、进程链表等等都要改改吧,见copy_process内部。 
从用户态的代码看fork();函数返回了两次,即在父子进程中各返回一次,父进程从系统调用中返回比较容易理解,子进程从系统调用中返回,那它在系统调用处理过程中的哪里开始执行的呢?这就涉及子进程的内核堆栈数据状态和task_struct中thread记录的sp和ip的一致性问题,这是在哪里设定的?copy_thread in copy_process

<code class="hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">*</span>childregs <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">*</span>current_pt_regs(); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//复制内核堆栈</span>
childregs<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-></span>ax <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//为什么子进程的fork返回0,这里就是原因!</span>

p<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-></span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">thread</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>sp <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> (unsigned long) childregs; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//调度到子进程时的内核栈顶</span>
p<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">-></span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">thread</span><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>ip <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> (unsigned long) ret_from_fork; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//调度到子进程时的第一条指令地址</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

按流程来说首先会进入do_fork,在do_fork里,对一些情况进行判断。如果没有什么危险的情况,则开始进入copy_process。 
copy_process函数在进程创建的do_fork函数中调用,主要完成进程数据结构,各种资源的初始化。初始化方式可以重新分配,也可以共享父进程资源,主要根据传入CLONE参数来确定。

  1. dup_task_struct()
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> task_struct *dup_task_struct(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> task_struct *orig)
{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> task_struct *tsk;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> thread_info *ti;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> node = tsk_fork_get_node(orig);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> err;

    tsk = alloc_task_struct_node(node);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!tsk)
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span>;

    ti = alloc_thread_info_node(tsk, node);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!ti)
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">goto</span> free_tsk;

    err = arch_dup_task_struct(tsk, orig);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (err)
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">goto</span> free_ti;

    tsk->stack = ti;
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"># ifdef CONFIG_SECCOMP</span>

    tsk->seccomp<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.filter</span> = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span>;
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"># endif</span>

    setup_thread_stack(tsk, orig);
    clear_user_return_notifier(tsk);
    clear_tsk_need_resched(tsk);
    set_task_stack_end_magic(tsk);

<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"># ifdef CONFIG_CC_STACKPROTECTOR</span>
    tsk->stack_canary = get_random_int();
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"># endif</span>

    atomic_set(&tsk->usage, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"># ifdef CONFIG_BLK_DEV_IO_TRACE</span>
    tsk->btrace_seq = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"># endif</span>
    tsk->splice_pipe = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span>;
    tsk->task_frag<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.page</span> = <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span>;

    account_kernel_stack(ti, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> tsk;

free_ti:
    free_thread_info(ti);
free_tsk:
    free_task_struct(tsk);
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span>;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li></ul>

tsk = alloc_task_struct_node(node);为task_struct开辟内存 
ti = alloc_thread_info_node(tsk, node);ti指向thread_info的首地址,同时也是系统为新进程分配的两个连续页面的首地址。 
err = arch_dup_task_struct(tsk, orig);复制父进程的task_struct信息到新的task_struct里, (dst = src;) 
tsk->stack = ti;task的对应栈 
setup_thread_stack(tsk, orig);初始化thread info结构 
set_task_stack_end_magic(tsk);栈结束的地址设置数据为栈结束标示(for overflow detection)

  1. gdb跟踪sys_clone 
    用gdb来跟踪sys_clone,设置以下断点 
    这里写图片描述
    运行后首先停在sys_clone处: 
    这里写图片描述
    然后是do_fork,之后是copy_process: 
    接着进入copy_thread: 
    ret_from_fork按照之前的分析被调用,跟踪到syscall_exit后无法继续.如果想在本机调试system call,那么当你进入system call时,系统已经在挂起状态了。
  2. 总结 
    新进程是从哪里开始执行的——————–? 
    在之前的分析中,谈到copy_process中的copy_thread()函数,正是这个函数决定了子进程从系统调用中返回后的执行.
<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">int copy_thread(unsigned long clone_flags, unsigned long sp,
    unsigned long arg, struct task_struct *p)
{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>

    *childregs = *current_pt_regs();
    childregs->ax = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (sp)
        childregs->sp = sp;

    p->thread.ip = (unsigned long) ret_from_fork;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>

子进程执行ret_from_fork

<code class="hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">ENTRY(ret_from_fork)
    CFI_STARTPROC
    pushl_cfi <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%eax</span>
    call schedule_tail
    GET_THREAD_INFO(<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%ebp</span>)
    popl_cfi <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%eax</span>
    pushl_cfi <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$0</span>x0202       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># Reset kernel eflags</span>
    popfl_cfi
    jmp syscall_exit
    CFI_ENDPROC
END(ret_from_fork)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

===================== 
在ret_from_fork之前,也就是在copy_thread()函数中*childregs = *current_pt_regs();该句将父进程的regs参数赋值到子进程的内核堆栈, 
*childregs的类型为pt_regs,里面存放了SAVE ALL中压入栈的参数 
故在之后的RESTORE ALL中能顺利执行下去. 
7. 未完待续。。 
8. 望手下留情

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值