zoukankan      html  css  js  c++  java
  • PHP多进程学习(三)__代码案例来了解父进程与子进程的执行顺序

    pcntl_fork创建子进程成功的话,系统就有了2个进程,一个为父进程,一个为子进程,父进程和子进程都继续向下执行,子进程的id号为$pid(父进程会获取子进程的$pid也就是$pid不为0,而子进程会获取$pid为0)在系统运行到$pid = pcntl_fork();时,在这个地方进行分支,父子进程各自开始运行各自的程序代码(通过if else语句判断$pid我们就可以在指定位置写上不同的逻辑代码)。

    代码的运行结果是parent 和child,很奇怪吧,为什么一个if和else互斥的代码中,都输出了结果?其实是像上边所说的,代码在pcntl_fork时,一个父进程运行parent,一个子进程运行了child。在代码结果上就显示了parent和child。至于谁先谁后的问题,这得要看系统资源的分配了。

    案例①

    <?php
    $pid = pcntl_fork();
     
    if($pid == -1) {
        //错误处理:创建子进程失败时返回-1.
        die('fork error');
    } else if ($pid) {
        //父进程会得到子进程号,所以这里是父进程执行的逻辑
        echo "parent 
    ";
        //等待子进程中断,防止子进程成为僵尸进程。
        pcntl_wait($status);
    } else {
        //子进程得到的$pid为0, 所以这里是子进程执行的逻辑。
        echo "child 
    ";
     
        exit;
    }
    # php fork.php       //结果
    parent 
    child 

    上述代码会经过多次执行,分别输出parent和child。貌似是优先执行父进程。那么输出的parent和child是否会有顺序之分?是父进程会先执行?下面继续测试。。。

    案例②

    <?php
    $pid = pcntl_fork();
     
    if($pid == -1) {
        die('fork error');
    } else if ($pid) {
        sleep(3);
        echo "parent 
    ";
        pcntl_wait($status);
    } else {
        echo "child 
    ";
     
        exit;
    }
    # php fork.php  //结果
    child 
    parent 

    我们在父进程中通过sleep来延缓执行,看看效果。
    结果是,很快输出了child,等待了接近3秒后,才输出parent。所以父进程和子进程的执行是相对独立的,没有先后之分。

    那么问题又来了?pcntl_wait是做什么用的?
    会挂起当前进程,直到子进程退出,如果子进程在调用此函数之前就已退出,此函数会立刻返回。子进程使用的资源将被释放。

    案例③

    <?php
    $pid = pcntl_fork();
     
    if($pid == -1) {
        die('fork error');
    } else if ($pid) {
        pcntl_wait ($status);
        echo "parent 
    ";
    } else {
        sleep(3);
        echo "child 
    ";
     
        exit;
    }
    # php fork.php  //结果 
    child 
    parent 

    上述代码,我们可以看到,父进程执行pcntl_wait时就已经挂起,直到等待3秒后输出child,子进程退出后。父进程继续执行,输出parent。

    案例④

    <?php
    define('FORK_NUMS', 3);
     
    $pids = array();
     
    for($i = 0; $i < FORK_NUMS; ++$i) {
        $pids[$i] = pcntl_fork();
        if($pids[$i] == -1) {
            die('fork error');
        } else if ($pids[$i]) {
            pcntl_waitpid($pids[$i], $status);
            echo "pernet 
    ";
        } else {
            sleep(3);
            echo "child id:" . getmypid() . " 
    ";
            exit;
        }
    }
    # php fork.php  //结果 
    child id:57534 
    pernet 
    child id:57538 
    pernet 
    child id:57540 
    pernet 

    上述代码,我们创建3个子进程,父进程分别挂起等待子进程结束后,输出parent。

    案例⑤

    <?php
    define('FORK_NUMS', 3);
     
    $pids = array();
     
    for($i = 0; $i < FORK_NUMS; ++$i) {
        $pids[$i] = pcntl_fork();
        if($pids[$i] == -1) {
            die('fork error');
        } else if ($pids[$i]) {
     
        } else {
            sleep(3);
            echo "child id:" . getmypid() . " 
    ";
            exit;
        }
    }
     
    foreach($pids as $k => $v) {
        if($v) {
            pcntl_waitpid($v, $status);
            echo "parent 
    ";
        }
    }
    # php fork.php  //结果
    child id:57579 
    child id:57581 
    child id:57580 
    parent 
    parent 
    parent 

    为什么上述代码跟例4的输出结果不一样?
    我们可以看到案例⑤的pcntl_waitpid函数放在了foreach中,foreach代码是在主进程中,也就是父进程的代码中。当执行foreach时,可能子进程已经全部执行完毕并退出。pcntl_waitpid会立刻返回,连续输出三个parent。
    在子进程中,需通过exit来退出,不然会产生递归多进程,父进程中不需要exit,不然会中断多进程。

    案例⑥

    <?php
     
    define('FORK_NUMS', 3);
     
    $pids = array();
     
    $fp = fopen('./test.log', 'wb');
    $num = 1;
     
    for($i = 0; $i < FORK_NUMS; ++$i) {
        $pids[$i] = pcntl_fork();
        if($pids[$i] == -1) {
            die('fork error');
        } else if ($pids[$i]) {
     
     
        } else {
            for($i = 0; $i < 5; ++$i) {
     
                flock($fp, LOCK_EX);
                fwrite($fp, getmypid() . ' : ' . date('Y-m-d H:i:s') . " : {$num} 
    ");
     
                flock($fp, LOCK_UN);
                echo getmypid(), ": success 
    ";
                ++$num;
            }
            exit;
        }
    }
     
    foreach($pids as $k => $v) {
        if($v) {
            pcntl_waitpid($v, $status);
        }
    }
     
    fclose($fp);
    # php fork.php         //结果 
    57641: success 
    57641: success 
    57641: success 
    57641: success 
    57641: success 
    57642: success 
    57642: success 
    57642: success 
    57642: success 
    57642: success 
    57643: success 
    57643: success 
    57643: success 
    57643: success 
    57643: success 
    //test.log  日志内容  
    57641 : 2018-02-02 15:55:48 : 1 
    57641 : 2018-02-02 15:55:48 : 2 
    57641 : 2018-02-02 15:55:48 : 3 
    57641 : 2018-02-02 15:55:48 : 4 
    57641 : 2018-02-02 15:55:48 : 5 
    57642 : 2018-02-02 15:55:48 : 1 
    57642 : 2018-02-02 15:55:48 : 2 
    57642 : 2018-02-02 15:55:48 : 3 
    57642 : 2018-02-02 15:55:48 : 4 
    57642 : 2018-02-02 15:55:48 : 5 
    57643 : 2018-02-02 15:55:48 : 1 
    57643 : 2018-02-02 15:55:48 : 2 
    57643 : 2018-02-02 15:55:48 : 3 
    57643 : 2018-02-02 15:55:48 : 4 
    57643 : 2018-02-02 15:55:48 : 5 

    我们可以看到三个子进程的pid,它们分别执行了5次,时间几乎是在同时。但是$num的值并没像我们期望的那样从1-15进行递增。子进程中的变量是各自独立的,互不影响。子进程会自动复制父进程空间里的变量。

     

     

    参考原文https://www.cnblogs.com/jkko123/p/6351690.html

  • 相关阅读:
    day60----日考
    css之单位
    如何装双系统win10下装Ubuntu
    css之Grid Layout详解
    css之position详解
    html+css的用户注册界面
    self-introduction
    ps常用操作
    前端基础之BOM和DOM
    emment语法
  • 原文地址:https://www.cnblogs.com/wt645631686/p/8405643.html
Copyright © 2011-2022 走看看