linux-创建子进程的过程与原理(fork讲解)

        我们知道,子进程可以被命令行创建,被fork函数创建,但是子进程创建了什么呢,是完全拷贝父进程函数?还是继承父进程数据呢?

首先我们要知道,进程的构成:进程=内核数据结构+可运行程序载入的代码和执行过程产生数据与部分属性数据。

linux-创建子进程的过程与原理(fork讲解)_第1张图片

 

        子进程也是进程,其实在cpu的角度来看,就是在数据结构上多了一个task_struct结点,那么PCB一定是多了一个。那么在结点的的角度来说,就是讲以父进程的PCB进程属性数据为模板拷贝了一份作为子进程的PCB。linux-创建子进程的过程与原理(fork讲解)_第2张图片

那么问题来了,既然PBC是父进程拷贝来的,那么代码和数据是不是也要拷贝呢?

这里代码确实是父子进程共享的,为什么呢?两个原因,首先在进程载入内存中的代码区,这个区域与常量区,在内存期间代码是不可被修改的,如果每创建一个子进程占用内存代码区一部分资源,这是非常浪费内存资源的,所以操作系统在创建子进程时候,使得子进程与其父进程共享一份代码。

谢谢你的阅读 

linux-创建子进程的过程与原理(fork讲解)_第3张图片

那么数据是否共享呢?其实在创建子进程的过程中数据是共享的 

linux-创建子进程的过程与原理(fork讲解)_第4张图片

但是到了后续,一旦父进程或子进程进行数据写入时候,这时候数据必须分开了。

会在数据写入前拷贝一份数据,然后让父进程数据独立,拷贝数据归于子进程

这个过程我们成为:写时拷贝(在进程改变数据段数据前,会发生拷贝,拷贝后才会写入)

linux-创建子进程的过程与原理(fork讲解)_第5张图片

为什么要分开数据段呢?应为如果父子代码和数据段一样的,那么他们的工作都是一样的,这是没有任何意义的。

总结:在代码创建的时候,子进程的内核数据结构是拷贝父进程的,而代码段父子进程共享,然后数据段的内容,在未发生写入时候父子共享,在发生写入时拷贝数据,子进程数据信息独立(写时拷贝)。

这里有个疑点,既然代码段一样,那么怎么使得父子进程做不同的事情呢?忘记了吗fork其实是一个函数

int main()
{
    //.......
    int ret=fork();//pid_i == int
    //.......
    return 0;
}

 不卖关子了!

当进程创建失败:返回值负数(ret<0)

当进程创建成功:子进程返回值为0(ret==0)

                             父进程返回值为子进程pid (ret==子pid)子进程pid>0

所以在有创建子进程的进程代码会有if...else...

int main()
{
    //.......
    int ret=fork();//pid_i == int
    if(ret>0)//父进程执行
    {
        //.........
    }
    else if(ret == 0)  //子进程执行
    {
        //.........
    }
    else  //进程创建失败执行
    {
        //.........
    }
    //.......
    return 0;
}


 

你可能感兴趣的:(linux,运维,服务器)