进程的描述和进程的创建

                                                                                        进程的描述和进程的创建

                                                                                                        20135109 高艺桐

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

一、进程的描述

1、1进程描述符task_struck数据结构(一)

(1)操作系统的三大功能:进程管理、内存管理、文件系统。

(2)

进程控制块PCB——task_struck

tty_struck控制台

fs_struck文件系统的描述

files_struck打开的文件描述符

mm_struck内存的描述

signal_struck信号的描述

(3)操作系统原理中的状态:就绪态、运行态、阻塞态

(4)

内核管理中的进程状态:

TASK_TUNNING(可运行)获得cpu控制权正在运行,被调度出去就是就绪态。

TASK_ZOMBIE(进程被终止)

TASK_interruotibie(阻塞态)

TASK_uninterruotibie(阻塞态)

(5)进程的标示符:pid(用来标识进程)

1、2进程描述符task_struck数据结构(二)

(1)state运行状态(指定进程状态)

(2)SMP条件编译(多处理器时会用到)

(3)

   

struct list_head tasks进程的链表,双向循环链表连接,链表可独立进行操作

(4)每个进程有自己独立的地址空间,32位x86有4G进程地址空间。

(5)pid_t pid标识一个进程

(6)

进程的父子关系:兄弟父子之间的关系通过双向链表连接起来。

(7)CPU相关的状态:thread_struct(sp、ip)进程上下文切换时期关键作用

(8)struct files_struct*files打开文件列表

(9)struck signal_struct *signal信号处理相关工作

二、进程的创建过程

2、1进程的创建概览及fork一个进程的用户态代码

(1)(文件系统、信号、内存)进程描述符中有相应的指针指向其内容,进行研究。

(2)

进程是怎么创建的:复制一份进程描述符,0号进程用代码写死,1号进程复制0号进程pcb,根据1号进程需要修改pid,最后加一个init可执行程序。

(3)

子进程从哪里开始执行:shell命令行怎么创建子进程的?

fork()用户态进行创建子进程

fork系统调用在父进程和子进程各返回一次

(4)fork在子进程中返回值是父进程的ID

2、2理解进程创建过程复杂代码的方法

(1)系统调用再回顾:

 

Int0x80是中断指令,把用户态堆栈转化到内核态堆栈,把CPU最关键的现场eip、esp保存到内核堆栈中去。

(2)

  

    子进程从哪里开始执行:fork()出的子进程在内核中开始返回。创建一个进程的框架:复制一份进程描述符,0号进程用代码写死,1号进程复制0号进程pcb,根据1号进程需要修改pid,最后加一个init可执行程序。

(3)创建进程过程中要做哪些事情:修改pcb,建立链表,修改分配内核堆栈,保存进程执行到哪个位置,保存sp、ip(避免发生混乱),需要有thread设定eip和esp位置。

2、3浏览进程的创建过程相关的关键方法

(1)

创建新进程在内核中执行的过程:

复制一个PCB——task_struct

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

更改复制过来的进程数据,比如pid,进程链表等

(2)系统调用内核处理函数:sys_fork、sys_clone、sys_vfork

(3)do_fork()中包含的copy process创建一个进程内容的主要代码

(4)arch dup_task_struct复制整个PCB(*dst=src*数据结构的值复制给dst)

(5)thread_info内核堆栈,创建一个页面,比较大(分配内核堆栈空间)

(6)p指向子进程的描述符

(7)copy_thread从子进程的pid找到了栈底的地址,把sp赋值过去,对父进程的栈底进行拷贝,包括栈顶数据,thread ip的内容。

2、4创建的新进程是从哪里开始执行的

(1)子进程从哪里开始执行的:ret_from_fork

(2)

Int指令和SAVE_ALL压到内核栈的内容。

(3)ret_from_fork 中的syscall_exit内核堆栈可正常返回到用户态(子进程的进程空间)。

2、5使用gdb跟踪创建新进程的过程

自己实验截图:

(1)把menu删除,克隆一份新的,把test_fork.c覆盖掉,编译内核,可以看到fork命令

(2)设置断点sys_clone,设置断点do_fork,设置断点dup_task_struck,设置断点copy_process,设置断点copy_thread,设置断点ret_from_fork

(3)在MenuOS中执行fork,就会发现fork函数停在了父进程中 

(4)继续执行之后,停在了do_fork的位置

(5)按s进入该函数,可以看到dst = src(也就是复制父进程的struct)

(6)按n继续追踪

(7)在copy_thread中,可以看到把task_pg_regs(p)也就是内核堆栈特定的地址找到并初始化

三、实验总结

  通过本周的学习,我了解到了Linux通过clone()系统调用实现fork(),fork(),vfork(),和clone()库函数都是根据各自需要的参数标志去调用clone(),然后由clone()调用do_fork,其中do_fork函数调用了copy_process()函数,然后让进程执行 Linux通过复制父进程创建新进程,fork、vfork、clone都是通过do_exit实现进程的创建。

  创建新进程的过程为:复制一个PCB——task_struct,给新进程分配一个新的内核堆栈,更改复制过来的进程数据,比如pid,进程链表等。子进程从ret_from_fork开始执行。

posted on 2016-03-31 14:39  20135109  阅读(4013)  评论(1编辑  收藏  举报