本文介绍了php pcntl多进程的例子,PHP pcntl多进程用法,PHP使用PCNTL系列的函数也能做到多进程处理一个事务,详细介绍了php pcntl_fork和pcntl_fork 的用法。
phpp pcntl多进程是什么?pcntl 实现php多进程的方法
php使用pcntl系列的函数也能做到多进程处理一个事务。
比如需要从数据库中获取80w条的数据,再做一系列后续的处理,这个时候,用单进程?你可以等到明年今天了。所以应该使用pcntl函数了。
假设,启动20个进程,将1-80w的数据分成20份来做,主进程等待所有子进程都结束了才退出:
复制代码 代码示例:
<?php
$max = 800000;
$workers = 20;
$pids = array();
for($i = 0; $i < $workers; $i++){
$pids[$i] = pcntl_fork();
switch ($pids[$i]) {
case -1:
echo "fork error : {$i} rn";
exit;
case 0:
$param = array(
'lastid' => $max / $workers * $i,
'maxid' => $max / $workers * ($i+1),
);
$this->executeWorker($input, $output, $param);
exit;
default:
break;
}
}
foreach ($pids as $i => $pid) {
if($pid) {
pcntl_waitpid($pid, $status);
}
}
这里当pcntl_fork出来以后,会返回一个pid值,这个pid在子进程中看是0,在父进程中看是子进程的pid(>0),如果pid为-1说明fork出错了。
使用一个$pids数组就可以让主进程等候所有进程完结之后再结束了。
二、php pcntl_fork和pcntl_fork 的用法
这是两个php的多线程的方法,在Windows下不可用,在linux下需要编译。
pcntl_fork()函数就是为当前的进程创建一个子进程。并且先运行父进程,返回的是子进程的PID,肯定大于零。在父进程的代码中可以用pcntl_fork(&$status)暂停父进程知道他的子进程有返回值。
注意:父进程的阻塞同时会阻塞子进程。但是父进程的结束不影响子进程的运行。
父进程运行完了会接着运行子进程,这时子进程会从执行pcntl_fork()的那条语句开始执行(包括此函数),但是此时它返回的是零(代表这是一个子进程)。在子进程的代码块中最好有exit语句,即执行完子进程后立即就结束。否则它会又重头开始执行这个脚本的某些部分(一直没有总结出规矩)。
注意两点:
1、子进程最好有一个exit;语句,防止不必要的出错;
例子:
复制代码 代码示例:
<?php
$pid = pcntl_fork();
//这里最好不要有其他的语句
if ($pid == -1) {
die('could not fork');
} else if ($pid) {
// we are the parent
pcntl_wait($status); //Protect against Zombie children
} else {
// we are the child
}
三、php使用pcntl_fork实现多进程下载图片的方法
php使用pcntl_fork实现多进程下载图片的方法,分析了pcntl_fork的原理与用法,以及使用pcntl_fork实现多进程下载图片的方法。
php如何使用pcntl_fork实现多进程下载图片
php pcntl_fork — 在当前进程当前位置产生分支,子进程,译注:fork是创建了一个子进程,父进程和子进程 都从fork的位置开始向下继续执行,不同的是父进程执行过程中,得到的fork返回值为子进程号,而子进程得到的是0。
注意:php有个pcntl_fork的函数可以实现多进程,但要加载pcntl拓展,而且只有在linux下才能编译这个拓展.
1,首先在ubuntu下编译pcntl.so,我的ubuntu下找不到pcntl的包。
于是创建一个文件夹下载了整个php包,在里面找到了pcntl包运行如下命令。
命令行:
# mkdir php
# cd php
# apt-get source php5
# cd php5-(WHATEVER_RELEASE)/ext/pcntl
# phpize
# ./configure (注一)
# make
# make install phpize 命令是用来准备 PHP 外挂模块的编译环境的
成功安装将建立 extname.so 并放置于 PHP 的外挂模块目录中(预设存放于 /usr/lib/php/modules/ 内),需要调整 php.ini,加入 extension=extname.so 这一行之后才能使用此外挂模块.
例子:
void pcntl_exec(string $path [,array $args [,array $envs ]])
pcntl_exec — 在当前进程空间执行指定程序
代码:
复制代码 代码示例:
$cmds=array(
array('/home/jerry/projects/www/test2.php'),
array('/home/jerry/projects/www/test3.php')
);
foreach($cmds as $cmd){
$pid=pcntl_fork();
if($pid==-1){
//进程创建失败
echo '创建子进程失败时返回-1';
exit(-1);
}
else if($pid){
//父进程会得到子进程号,所以这里是父进程执行的逻辑
pcntl_wait($status,WNOHANG);
}
else{
//子进程处理逻辑
sleep(5);
pcntl_exec('/usr/bin/php',$cmd);
exit(0);
}
}
例2,php多进程方式实现多图片同步下载。
复制代码 代码示例:
#!/usr/bin/php
<?php
// 需要抓取的网页地址
$url = 'http://www.jb200.com';
$content =
file_get_contents($url);
preg_match_all('/<imgs+src="(.*?)"/', $content, $matches,PREG_SET_ORDER);
echo "已发现".count($matches)."张图片n";
list($sm, $ss) = explode(" ", microtime());
foreach ($matches as $k => $val)
{
$pid[$k] = pcntl_fork();
if(!$pid[$k])
{
download($url, $val);
// 子进程要exit否则会进行递归多进程,父进程不要exit否则终止多进程
exit(0);
}
if ($pid[$k])
{
// pcntl_waitpid($pid[$k], $status, WUNTRACED);
}
}
echo "下载完成n";
list($em, $es) = explode(" ", microtime());
echo "用时:",($es+$em) - ($ss + $sm),"n";
/**
* 抓取网页图片
*
*/
function download($url, $val)
{
$pic_url = $val[1];
if (strpos($val[1], '//') !== false)
{
;
}
elseif (preg_match('@^(.*?)/@', $val[1], $inner_matches) == 0)
{
$pic_url = $url.$val[1];
}
elseif (preg_match('@[:.]@', $inner_matches[1], $tmp_matches) == 0)
{
$pic_url = $url.$val[1];
}
$pic = file_get_contents($pic_url);
if ($pic === false)
{
return;
}
preg_match('@/([^/]+)$@', $pic_url, $tmp_matches);
// 可使用assert处理异常
$pic_file_name = $tmp_matches[1];
$f = fopen("tmp/".$pic_file_name, "wb"); #
fwrite($f, $pic);
fclose($f);
}
/* End of file pcntl_fork.php */
?>