20135311傅冬菁
分析Linux内核创建一个新进程的过程
一、学习内容
进程控制块——PCB task_struct数据结构
PCB task_struct中包含:
进程状态、
进程打开的文件、
进程优先级信息
操作系统管理的三个功能:
1.进程管理 2.内存管理 3.文件系统
Linux进程的状态:
进程状态分析:
long state是进程的运行状态,-1是未执行,0是执行中,大于0则是暂停;
*stack 是建立一个内核堆栈;
flags 是定义了每个进程的标识符;
list_head tasks 这部分是定义双向链表的;
mm_struct *mm 这部分是定义内存管理中,进程的地址空间;
以上这部分代码也属于进程任务堆栈;
定义进程的PID标识符;
定义进程间父子的继承关系;
与CPU相关的线程的定义;(在Linux系统中,系统将线程看作是轻量级的进程,基本上将进程和线程一视同仁)
该部分定义了线程的数据结构、文件结构、信号量等;
进程创建分析:
大部分进程都是由fork()函数创建出来的;而调用fork()函数实际上是调用了clone();
fork()函数代码及分析:
#include2 #include 3 #include 4 int main(int argc, char * argv[]) 5 { 6 int pid; 7 /* fork another process */ 8 pid = fork();//调用fork创建一个进程; 9 if (pid < 0) 10 { 11 /* error occurred */12 fprintf(stderr,"Fork Failed!");13 exit(-1);14 } 15 else if (pid == 0) 16 {17 /* child process */ 18 printf("This is Child Process!\n");//创建子进程 fork系统调用在父进程和子进程各返回一次 19 } 20 else 21 { 22 /* parent process */23 printf("This is Parent Process!\n");24 /* parent will wait for the child to complete*/25 wait(NULL);26 printf("Child Complete!\n");27 }28 }
fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建。
创建新进程是通过复制当前进程实现的。do_fork
主要是复制了父进程的task_struct
,然后修改必要的信息,从而得到子进程的task_struct
。复制一个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,而非复制内核堆栈
要修改复制过来的进程数据,比如pid、进程链表等。
二、实验过程
三、学习小结
1.Linux通过clone()系统调用实现fork()
2.fork(),vfork(),和clone()库函数都是根据各自需要的参数标志去调用clone(),然后由clone()调用do_fork。其中do_fork函数调用了copy_process()函数,然后让进程执行 Linux通过复制父进程创建新进程,fork、vfork、clone都是通过do_exit实现进程的创建。
3.进程创建的内容:
复制一个PCB struct
给新进程分配一个新的内核堆栈
对子进程进行初始化,修改复制的数据。
4.父进程和子进程各返回一次。