zoukankan      html  css  js  c++  java
  • CLI下另一种多进程实现方式----PCNTL

    有些时候,你需要对一些脚本进行优化,以期跑的更快,在更短的时间内完成任务。PCNTL是一个不错的选择,它可以fork多个进程,来协同完成一个任务,理论上完成的时间将会和进程数成反比。

    不过,PCNTL只能用于CLI模式下,不能用于Web服务器环境,否则可能会带来意料之外的错误,不推荐使用。

    • 安装PCNTL扩展:

      wget http://cn2.php.net/distributions/php-5.3.27.tar.bz2
      tar -jxvf php-5.3.27.tar.bz2
      cd php-5.3.27/ext/pcntl/
      phpize && ./configure && make install
      echo "extension=pcntl.so" >> /application/php5.3.27/lib/php.ini
      kill -USR2 `cat /var/run/php-fpm.pid`
      下载->解压->编译->添加扩展模块->重启php-fpm

      注意:线上web服务器中,PHP编译时已经集成该函数,不需要再单独添加,否则会报warning。

      • 程序实例:

        程序流程在注释中已经比较详细的说明了,这里不再单独叙述。

      • 执行结果:

        从结果中可以看出来,虽然程序中fork子进程是有序的,但是在实际执行中并不一定是有序的,进程完成的顺序与进程开始的顺序也不是保持一致的。
        fork前,子进程可以继承父进程的东西,但是在pcntl_fork()后子进程和父进程就没有任何继承关系了。在子进程里创建的东西是子进程的,在父进程创建的东西是父进程的,可以完全看成是两个独立的进程。
        fork后,程序出了分岔,派生出了两个进程,具体哪个先运行,哪个先结束就看该系统的调度算法了。

      • demo
      • <?php
        /**
         * pcntl test
         * @author: xxxx
         */
        
        set_time_limit(0);
        
        //如果找不到pcntl_fork函数,直接退出
        if (! function_exists('pcntl_fork')) echo "PCNTL functions not available on this PHP installation
        ";
        
        //脚本运行开始
        $start =  time();
        echo "
        SCRIT RUN AT: ", date('Y-m-d H:i:s', $start), "
        ";
        
        //从CLI取参数
        //默认跑10个进程
        $pmax = empty($argv[1]) ? 10 : $argv[1];
        //父进程pid
        $ppid = getmypid(); 
        for ($i = 1; $i <= $pmax; ++$i) {
            //开始产生子进程
            $pid = pcntl_fork();
            switch ($pid) {
            case -1:
                // fork失败
                echo "Fork failed!
        ";
                break;
            case 0:
                // fork成功,并且子进程会进入到这里
                sleep(1);
                $cpid = getmypid(); //用getmypid()函数获取当前进程的PID
                echo "FORK: Child #{$i} #{$cpid} is running...
        ";
                //子进程要exit否则会进行递归多进程,父进程不要exit否则终止多进程
                exit($i);
                break;
            default:
                // fork成功,并且父进程会进入到这里
                if ($i == 1) {
                    echo "Parent #{$ppid} is running...
        ";
                }
                break;
           }
        }
        
        //父进程利用while循环,并且通过pcntl_waitpid函数来等待所有子进程完成后才继续向下进行
        while (pcntl_waitpid(0, $status) != -1) {
            //pcntl_wexitstatus返回一个中断的子进程的返回代码,由此可判断是哪一个子进程完成了
            $status = pcntl_wexitstatus($status); 
            echo "Child $status has completed!
        ";
        }
        
        echo "Parent #{$ppid} has completed!
        ";
        
        echo "
        SCRIT END AT: ", date('Y-m-d H:i:s', $start), "
        ";
        echo "TOTAL TIMEEEE: " . (time() - $start)/60;
        echo "
        ++++++++++++++++++++++++++++++++++++++++++++OK++++++++++++++++++++++++++++++++++++++++++++++++++
        ";
        ?>
  • 相关阅读:
    深入浅出Win32多线程程序设计【2】线程控制
    深入浅出Win32多线程程序设计【1】基本概念
    在两个ASP.NET页面之间传递值
    Javascript基础
    DataGrid的几个小技巧
    推荐取代Visio的中国人的软件——Edraw
    ASP.NET如何防范SQL注入攻击
    软件版本号规定原则
    三层体系结构总结(三)
    .Net工具 .NET文档生成工具2.2
  • 原文地址:https://www.cnblogs.com/lixiuran/p/4803099.html
Copyright © 2011-2022 走看看