• 5进程创建FORK


    1. fork函数初识

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

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ua7kK5C4-1668515539934)(https://gitee.com/du-weiwei/typora/raw/master/image-20220311175555538.png)]

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

    #include 
    #include 
    #include 
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    运行结果为

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

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

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fbyr8z1M-1668515539935)(https://gitee.com/du-weiwei/typora/raw/master/image-20220311175811031.png)]

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


    2. fork函数返回值

    fork函数有两个返回值

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

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

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

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

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

    #include 
    #include 
    #include 
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

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

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

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uEE8tBfp-1668515539935)(https://gitee.com/du-weiwei/typora/raw/master/image-20220311213052411.png)]

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

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

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


  • 相关阅读:
    KT148A语音芯片按键版本一对一触发播放常见的问题集锦FAQ_V4
    (三)行为模式:7、观察者模式(Observer Pattern)(C++示例)
    OceanBase开源获信通院认可:开源300万行核心代码、社区答疑超3万次
    单臂路由 - 实验配置
    论文解读( N2N)《Node Representation Learning in Graph via Node-to-Neighbourhood Mutual Information Maximization》
    【算法】位运算算法——消失的两个数字(困难)
    JCMsuite应用—单光子光源耦合至光纤
    java实用代码-----HttpsUtil
    什么是操作系统
    JumpServer rce深入剖析
  • 原文地址:https://blog.csdn.net/m0_51723227/article/details/127873293