PHP多进程编程
多进程编写
pcntl_fork
函数来创建一个子进程,系统调用的是使用clone
函数来创建的。
问题
使用多进程开发,必须清除的几件事:
- 到底创建了几个进程
- 每个进程
$count
是多少 - 每个进程到底从哪个地方开始运行代码
fork
之后,每个进程的变量$i, $count
的值到底是多少- 每个进程运行到哪一行语句结束
<?php
$count = 10;
for ($i = 0; $i < 2; $i++) {
$pid = pcntl_fork();
if ($pid == 0) {
$count += 1;
} else {
$count *= 10;
}
}
fprintf(STDOUT, "poid=%d, count=%d\n", posix_getpid(), $count);
运行结果
[root@jb51 process]# php demo11.php
poid=5677, count=1000
poid=5683, count=110
poid=5684, count=101
[root@jb51 process]# poid=5685, count=12
感觉是不是和预想的一些值有出处。
分析
- 开始运行:
php demo11.php
- for循环开始
- 遇到
fork
函数之后,创建了一个子进程,假设命名这个子进程为child1
,变量$i = 0
目前为0,$count = 10
,子进程child1
继续执行,这个时候满足$pid == 0
,进行$count += 1
,此时$count = 11
,$i++
之后变成1。 CPU
现在要调度到父进程,执行$count *= 10
,此时$count = 100
,$i++
之后变为1- 假设父进程还在继续运行,
$count=100
了,$i=1
了,再次执行fork
,又产了一个子进程,命名为child2
;假设CPU
还是在调度父进程,$count = 1000
,$i = 2
,正好for
循环退出,父进程的最终结果是:$count = 1000
CPU
运行child2
子进程,执行$count += 1
,那么$count = 101
,$i = 2
,child2
的子进程最终结果是:$count = 101
CPU
又调度到child1
子进程,此时变量$count = 11
,$i = 1
,这个时候child1
执行pcntl_fork
函数,产生的子进程名称为child3
,此时$i=1,$count = 11
,会复制数据,child1
继续执行,肯定是满足child1是child3
的父亲,也算是一个父进程,会走else
,此时$count = 11 * 10 = 110
,此时$i = 2
了,此时child1
的最终结果:$count = 110
CPU
又调度到child3
子进程,因为会复制数据,基础数据:$count = 11
,$i = 1
,最终结果为:$count = 12
关系
child1
和child2
是兄弟进程,父进程是当前的主进程child3
的父亲是child1
我们可以加上一个死循环来阻塞一下,看看进程树
<?php
$count = 10;
for ($i = 0; $i < 2; $i++) {
$pid = pcntl_fork();
if ($pid == 0) {
$count += 1;
} else {
$count *= 10;
}
}
while (1) {
fprintf(STDOUT, "poid=%d, count=%d\n", posix_getpid(), $count);
sleep(10);
}
这样可以很清楚的看到几个进程之间的关系。
稍作修改,加上一个break
之后又是什么情况
<?php
$count = 10;
for ($i = 0; $i < 2; $i++) {
$pid = pcntl_fork();
if ($pid == 0) {
$count += 1;
} else {
$count *= 10;
break;
}
}
fprintf(STDOUT, "poid=%d, count=%d\n", posix_getpid(), $count);
分析
CPU
调度主进程,执行fork
之后,就产生了一个子进程,命名为child1
,并且复制父进程的代码段,即此时:$i = 0, $count =10
- 假设
CPU
继续执行主进程,必然会满足else
分支,此时$count = 100,$i = 1
,这个时候遇到break
退出了for
循环,主进程就结束了,主进程的最终结果:$count = 100
CPU
调度到child1
子进程,执行if
分支,$count = 11, $i = 1
,还是小于2,会继续执行该进程,必然会执行pcntl_fork
函数,又创建了有一个子进程,命名为child2
,复制数据$count = 11, $i = 1
。- 假设
CPU
还是继续调度child1
进程,此时它已经是一个父亲了,此时满足else
分支 ,$count = 110
,遇到break
退出,child1
进程的最终结果:$count = 110
CPU
切换调度到child2
子进程,$count = 11, $i = 1
,满足if
分支,此时$count = 12, $i = 2
,退出循环
进程关系:
child1
子进程的父亲是主进程child2
子进程的父亲是child1