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

 

郑斌   原创作品转载请注明出处

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

 

实验要求:

 

  • 阅读理解task_struct数据结构http://codelab.shiyanlou.com/xref/linux-3.18.6/include/linux/sched.h#1235;
  • 分析fork函数对应的内核处理过程sys_clone,理解创建一个新进程如何创建和修改task_struct数据结构;
  • 使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone ,验证您对Linux系统创建一个新进程的理解,推荐在实验楼Linux虚拟机环境下完成实验。 特别关注新进程是从哪里开始执行的?为什么从那里能顺利执行下去?即执行起点与内核堆栈如何保证一致。
  • 根据本周所学知识分析fork函数对应的系统调用处理过程,撰写一篇署名博客,并在博客文章中注明“真实姓名(与最后申请证书的姓名务必一致) + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”,博客内容的具体要求如下:
    • 题目自拟,内容围绕对Linux系统如何创建一个新进程进行;
    • 可以结合实验截图、绘制堆栈状态执行流程图等;
    • 博客内容中需要仔细分析新进程的执行起点及对应的堆栈状态等。
    • 总结部分需要阐明自己对“Linux系统创建一个新进程”的理解

 

实验环境:

    本实验在实验楼Linux环境下完成。

 

实验步骤:

   

  根据实验指导。我们先删除menu并clone以后 ,删除test_fork.c和test.c 后进行make rootfs。 

MENUOS运行后help可以看到多了一个fork的功能。

当执行fork命令后,会输出相应的信息。

 

然后使用gdb进行调试。

我们在 sys_clone ,do_fork ,dup_task_struct , copy_process, copy_thread, ret_from_fork 等处设置断点。

 

1)程序首先执行到do_fork函数。

我们在http://codelab.shiyanlou.com/xref/linux-3.18.6/kernel/fork.c中看可以看到内核部分do_fork函数的相关代码。该函数功能为实现进程的创建。

如下图所示,注意到其中的copy_process()函数,也是gdb中下一处将要遇到的断点。

我们继续调试。

2)执行到copy_process。

该函数主要功能为拷贝进程信息。

在查看在copy_process内核代码中,定义了进程id、进程task_struct等信息。同时有p=dup_task_struct(current)。

复制当前的进程信息结构体给p,这里不妨猜测程序执行下一个遇到的断点为dup_task_struct。

 

3)执行到dup_task_struct函数。

 

4)接着依次执行到copy_thread函数。

可以看到有拷贝设置寄存器信息,esp,eip等内容。

 

5)然后是ret_from_fork。

这是子进程在内核中执行的起点。

之后就gdb跟踪不到了。

 

基于以上的分析,根据本人理解,新进程创建过程的执行流程图如下。

 

 

实验总结:

 

通过本次实验,学习了:

1进程控制块PCB---task_struct包括状态、描述符、打开的文件系统、标记、链表信息、内存管理、信号等等信息。

2Linux系统中,进程的状态在就绪和运行状态都是task_running状态。是否运行取决于是否在CPU的时序上运行,跟windows中类似,当等待事件发生或者资源分配等,进程变为阻塞状态, 事件发生或者等待的资源分配后转为就绪状态。

3Linux系统中进程是用一个双向循环链表的结构链接起来的。每个进程通过pid标识来区分。第一个进程创建后,当要创建新的进程,先复制父进程的内容,然后修改寄存器、标识符等信息。

4Linux系统中fork、vfork和clone三个系统调用都是通过调用do_fork来实现进程的创建。

posted @ 2015-04-12 23:18  夕羊  阅读(246)  评论(0编辑  收藏  举报