Linux内核分析实验六

Posted YoungX0701

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux内核分析实验六相关的知识,希望对你有一定的参考价值。

==========================================================================

刘旸 + 原创作品转载请注明出处

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

==========================================================================


理论基础:

  进程描述符(task_struct)

  用来描述进程的数据结构,可以理解为进程的属性。比如进程的状态、进程的标识(PID)等,都被封装在了进程描述符这个数据结构中,该数据结构被定义为task_struct

 

  进程控制块(PCB)

  是操作系统核心中一种数据结构,主要表示进程状态。

 

  进程状态



  创建一个进程至少涉及的函数:

  sys_clonedo_forkdup_task_struct

  copy_processcopy_threadret_from_fork

 

下面我们通过跟踪fork()来观察Linux是如何创建新进程。

    1.fork()添加到MenuOS

 


    2.编写fork()的具体实现代码。


 

    3.编译并启动MenuOS

 

    4.使用gdb调试MenuOS,在sys_fork()处设置断点,continue。


 

    5.在MenuOS中键入命令fork,使其在sys_fork()处停下。


 

    6.用list命令查看代码,s命令追踪语句执行状况。







 

分析与总结:

    1.不论是使用fork()/vfork()还是clone()来创建进程,最终都是通过do_fork()方法来实现的。

 

    2.do_fork()流程:

      1)首先调用copy_process()为子进程复制出一份进程信息,如果是vfork()则初始化完成处理信息;

      2)然后调用wake_up_new_task将子进程加入调度器,为之分配CPU,如果是vfork(),则父进程等待子进程完成exec替换自己的地址空间。

 

    3.copy_process()流程:

      1)首先调用dup_task_struct()复制当前的task_struct,检查进程数是否超过限制;

      2)接着初始化自旋锁、挂起信号、CPU 定时器等;

      3)然后调用sched_fork初始化进程数据结构,并把进程状态设置为TASK_RUNNING,复制所有进程信息,包括文件系统、信号处理函数、信号、内存管理等;

      4)调用copy_thread()初始化子进程内核栈,为新进程分配并设置新的pid。

 

    4.dup_task_struct()流程:

      1)调用alloc_task_struct_node()分配一个 task_struct 节点;

      2)调用alloc_thread_info_node()分配一个 thread_info 节点,其实是分配了一个thread_union联合体,将栈底返回给 ti;

      3)最后将栈底的值 ti 赋值给新节点的栈。

 

    5.sched_fork():sched_fork()大致完成了两项重要工作,一是将子进程状态设置为 TASK_RUNNING,二是为其分配 CPU。

 

    6.copy_thread():这部分为我们解释了两个及其重要的问题:

      1)为什么fork()在子进程中返回0,原因是childregs->ax = 0;这段代码将子进程的 eax 赋值为0。

      2)p->thread.ip = (unsigned long) ret_from_fork;将子进程的ip设置为ret_form_fork的首地址,因此子进程是从ret_from_fork开始执行的。

 

最后附上fork流程图:




以上是关于Linux内核分析实验六的主要内容,如果未能解决你的问题,请参考以下文章

实验六分析Linux内核创建一个新进程的过程

Linux内核分析实验六

Linux内核分析实验六

实验六:分析Linux内核创建一个新进程的过程

Linux内核分析实验五

Linux内核分析实验五