5进程创建FORK

Posted 捕获一只小肚皮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5进程创建FORK相关的知识,希望对你有一定的参考价值。

文章目录

1. fork函数初识

fork函数的作用从已存在的进程中创建一个新的进程,而新进程被称为子进程,原进程称为父进程,我们先看一下当执行fork后会发生什么.

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度

也就是说 当一个进程调用fork之后,就有两个二进制代码相同的进程,而且它们都从fork以后开始运行到相同的地方,即每个进程都将可以开始它们自己的旅程,如下程序:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()

    pid_t  pid;
    printf("before,pid=%d,ppid=%d\\n",getpid(),getppid());
    pid = fork();  //创建子进程
    printf("after,pid=%d,ppid=%d\\n",getpid(),getppid());
    return 0;

运行结果为

[MakeBigMoney@VM-12-5-centos ~]$ ./test 
before,pid=1390,ppid=29550
after,pid=1391,ppid=1390
after,pid=1390,ppid=29550

可以看到进程1390执行了beforeafter,进程1391也执行了after,但是1391却没有执行before,这是为什么呢?

用下图便可解释上面程序的原因:

所以,fork之前父进程独立执行,fork之后,父子两个执行流分别执行。注意,fork之后,谁先执行完全由调度器 决定。


2. fork函数返回值

fork函数有两个返回值

  • 给子进程返回0
  • 给父进程返回子进程的PID

那它为什么有两个返回值呢,在了解这个概念之前,我们先说一下写时拷贝.

一种写的时候才分配内存空间的拖延策略

说白了就是如果拷贝方对于被拷贝方的数据暂时只有读的需求时,变不开空间,直接用指针指向被拷贝方的空间,当需要写的时候才为其分配一块新的空间,关系如下:

而fork创建子进程时候,便是以父进程为模板,把代码和数据写时拷贝给子进程,根据这个原理,我们在按照这个思路进行理解下面的程序:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()

    pid_t  my_pid;
    printf("before,pid=%d,ppid=%d\\n",getpid(),getppid());
    my_pid = fork();  //创建子进程
    printf("after,pid=%d,ppid=%d\\n",getpid(),getppid());
    return 0;

一开始父进程执行到了fork位置并创建子进程,然后系统给子进程进行写时拷贝,子进程便拥有了一份和上面一模一样的代码.

fork调用结束,父子进程便可以开始自己的独立旅行,于是父进程代码的my_pid被赋值,同理!!!,子进程的my_pid这时候也需要被赋值,于是

系统便重新开辟一块空间给子进程,既然拥有了两个不同的my_pid,自然就有两个值了

(创建子进程过程如上图)

对于fork可以返回两个值的说法的理解,不如说是两个同名的变量各自接收了一份进程的数据而表现出来fork返回了两个值.

而写时拷贝从另一方面来说,也就保证了进程之间的独立性(因为需要写入的数据都各自私有了,互不影响)


以上是关于5进程创建FORK的主要内容,如果未能解决你的问题,请参考以下文章

linux进程原语之fork()(原创!)

Linux——随笔

linux 进程创建clonefork与vfork

已失效的进程,fork()

golang 进程创建,fork,以及热重启(无缝升级)

Linux进程控制