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

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

一、阅读理解task_struct数据结构:

1.每一个用户态进程对应一个pcb,也就是进程控制块,在内核中对应的说法就是进程描述符。

2.task_struct的结构体包含了进程的状态,进程的堆栈,进程的标识符,进程的优先级,进程的调度策略,进程的打开的文件信息等等的进程的相关信息。

3.进程有三种状态,终止状态,运行状态,阻塞状态。并且每一个进程都有自己的一个进程堆栈,进程对应着一个标识符,操作系统通过标识符来唯一的确认每一个进程;每一个进程的优先级是不一样的。

4.进程的调度策略是不同的操作系统有着不同的调度策略。每一个进程可能都会打开很多的文件,这些文件都会在进程描述符里记录相关信息。 

 

二、分析fork函数对应的内核处理过程sys_clone,理解创建一个新进程如何创建和修改task_struct数据结构:

1.首先是fork触发系统调用sys_clone,然后最终执行的是do_fork.

2.fork创建了两个进程,一个父进程,一个子进程,其中子进程是对父进程的拷贝,它从父进程处复制了整个进程的地址空间,只有进程号和一些计时器等等是自己独有的,由于要复制很多资源,所以fork创建进程是很慢的。

3.fork执行一次有两次返回值,在父进程里返回新建的子进程编号,在子进程里返回0.由于创建进程的三种方式最终都是调用do_fork.

4.创建子进程的一个重要的过程是复制父进程里面的资源,有看到下面的copy_process函数,所以基本判断是复制资源的函数.这段代码是创建子进程的精华部分,所有的创建进程上下文,为新进程设置新的pid,还有复制代码,都在这一部分了

 

三、使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone:

特别关注新进程是从哪里开始执行的?为什么从哪里能顺利执行下去?即执行起点与内核堆栈如何保证一致

设置了6个断点:sys_clone,do_fork,dup_task_struct,copy_process,copy_thread,ret_from_fork

1.Sys_clone:

2.do_fork 系统内核调用:

3.copy_process 复制父进程的所有信息给子进程,dup_task_struct 中为子进程分配了新的堆栈:

 4.调用 sched_fork,并把新进程设置为 TASK_RUNNING,copy_thread 中把父进程的寄存器上下文复制给子进程:

 5.设置 ret_from_fork 的地址为 eip 寄存器的值:

 

四、对“Linux系统创建一个新进程”的理解:

1.创建一个新进程在内核中的执行过程 fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建;

2.Linux通过复制父进程来创建一个新进程,那么这就给我们理解这一个过程提供一个想象的框架: 复制一个PCB——task_struct err = arch_dup_task_struct(tsk, orig); 要给新进程分配一个新的内核堆栈 ti = alloc_thread_info_node(tsk, node); tsk->stack = ti; setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈

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

 

posted @ 2017-03-29 20:44  somnus赤系  阅读(420)  评论(0编辑  收藏  举报