<?php
define('FORK_NUMS', 3);
$pids = array();
for($i = 0; $i < FORK_NUMS; ++$i) {
$pids[$i] = pcntl_fork();
if($pids[$i] == -1) {
die('fork error');
} else if ($pids[$i]) {
} else {
sleep(3);
echo "child id:" . getmypid() . " \n";
exit;
}
}
foreach($pids as $k => $v) {
if($v) {
pcntl_waitpid($v, $status);
echo "parent \n";
}
}
输出结果如下:
child id:19118
child id:19119
child id:19120
parent
parent
parent
为什么上述代码跟例4的输出结果不一样?
我们可以看到例5的pcntl_waitpid函数放在了foreach中,foreach代码是在主进程中,也就是父进程的代码中。当执行foreach时,可能子进程已经全部执行完毕并退出。pcntl_waitpid会立刻返回,连续输出三个parent。
(*在子进程中,需通过exit来退出,不然会产生递归多进程,父进程中不需要exit,不然会中断多进程。)
例6如下:
<?php
define('FORK_NUMS', 3);
$pids = array();
$fp = fopen('./test.log', 'wb');
$num = 1;
for($i = 0; $i < FORK_NUMS; ++$i) {
$pids[$i] = pcntl_fork();
if($pids[$i] == -1) {
die('fork error');
} else if ($pids[$i]) {
} else {
for($i = 0; $i < 5; ++$i) {
flock($fp, LOCK_EX);
fwrite($fp, getmypid() . ' : ' . date('Y-m-d H:i:s') . " : {$num} \r\n");
flock($fp, LOCK_UN);
echo getmypid(), ": success \r\n";
++$num;
}
exit;
}
}
foreach($pids as $k => $v) {
if($v) {
pcntl_waitpid($v, $status);
}
}
fclose($fp);
代码如上:我们创建三个子进程,来同时向test.log文件写入内容,test.log内容如下:
19507 : 2016-03-16 20:40:52 : 1
19507 : 2016-03-16 20:40:52 : 2
19507 : 2016-03-16 20:40:52 : 3
19507 : 2016-03-16 20:40:52 : 4
19507 : 2016-03-16 20:40:52 : 5
19509 : 2016-03-16 20:40:52 : 1
19509 : 2016-03-16 20:40:52 : 2
19509 : 2016-03-16 20:40:52 : 3
19509 : 2016-03-16 20:40:52 : 4
19509 : 2016-03-16 20:40:52 : 5
19508 : 2016-03-16 20:40:52 : 1
19508 : 2016-03-16 20:40:52 : 2
19508 : 2016-03-16 20:40:52 : 3
19508 : 2016-03-16 20:40:52 : 4
19508 : 2016-03-16 20:40:52 : 5
我们可以看到三个子进程的pid,它们分别执行了5次,时间几乎是在同时。但是$num的值并没像我们期望的那样从1-15进行递增。子进程中的变量是各自独立的,互不影响。子进程会自动复制父进程空间里的变量。
如何在进程中共享数据?
我们通过php的共享内存函数shmop来实现。
<?php
define('FORK_NUMS', 3);
$pids = array();
$fp = fopen('./test.log', 'wb');
$num = 1;
//共享内存段的key
$shmKey = 123;
//创建共享内存段
$shmId = shmop_open($shmKey, 'c', 0777, 64);
//写入数据到共享内存段
shmop_write($shmId, $num, 0);
for($i = 0; $i < FORK_NUMS; ++$i) {
$pids[$i] = pcntl_fork();
if($pids[$i] == -1) {
die('fork error');
} else if ($pids[$i]) {
//阻塞,等待子进程退出
//注意这里,如果是非阻塞的话,$num的计数会出现问题。
pcntl_waitpid($pids[$i], $status);
} else {
//读取共享内存段中的数据
$num = shmop_read($shmId, 0, 64);
for($i = 0; $i < 5; ++$i) {
fwrite($fp, getmypid() . ' : ' . date('Y-m-d H:i:s') . " : {$num} \r\n");
echo getmypid(), ": success \r\n";
//递增$num
$num = intval($num) + 1;
}
//写入到共享内存段中
shmop_write($shmId, $num, 0);
exit;
}
}
//shmop_delete不会实际删除该内存段,它将该内存段标记为删除。
shmop_delete($shmId);
shmop_close($shmId);
fclose($fp);
内容版权声明:除非注明,否则皆为本站原创文章。
