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 = 101CPU又调度到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 = 110CPU又调度到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

