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\n"; //脚本运行开始 $start = time(); echo "\nSCRIT RUN AT: ", date('Y-m-d H:i:s', $start), "\n"; //从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!\n"; break; case 0: // fork成功,并且子进程会进入到这里 sleep(1); $cpid = getmypid(); //用getmypid()函数获取当前进程的PID echo "FORK: Child #{$i} #{$cpid} is running...\n"; //子进程要exit否则会进行递归多进程,父进程不要exit否则终止多进程 exit($i); break; default: // fork成功,并且父进程会进入到这里 if ($i == 1) { echo "Parent #{$ppid} is running...\n"; } break; } } //父进程利用while循环,并且通过pcntl_waitpid函数来等待所有子进程完成后才继续向下进行 while (pcntl_waitpid(0, $status) != -1) { //pcntl_wexitstatus返回一个中断的子进程的返回代码,由此可判断是哪一个子进程完成了 $status = pcntl_wexitstatus($status); echo "Child $status has completed!\n"; } echo "Parent #{$ppid} has completed!\n"; echo "\nSCRIT END AT: ", date('Y-m-d H:i:s', $start), "\n"; echo "TOTAL TIMEEEE: " . (time() - $start)/60; echo "\n++++++++++++++++++++++++++++++++++++++++++++OK++++++++++++++++++++++++++++++++++++++++++++++++++\n"; ?>