AI智能
改变未来

PHP多进程学习(三)父进程与子进程的执行顺序,进程中共享数据


案例1

<?php$pid = pcntl_fork();if($pid == -1) {//错误处理:创建子进程失败时返回-1.die('fork error');} else if ($pid) {//父进程会得到子进程号,所以这里是父进程执行的逻辑echo "parent \\n";//等待子进程中断,防止子进程成为僵尸进程。pcntl_wait($status);} else {//子进程得到的$pid为0, 所以这里是子进程执行的逻辑。echo "child \\n";exit;}

上述代码会经过多次执行,分别输出parent和child

案例2

<?php$pid = pcntl_fork();if($pid == -1) {die('fork error');} else if ($pid) {sleep(3);echo "parent \\n";pcntl_wait($status);} else {echo "child \\n";exit;}

结果是,很快输出了child,等待了接近3秒后,才输出parent。所以父进程和子进程的执行是相对独立的,没有先后之分。

pcntl_wait是:
会挂起当前进程,直到子进程退出,如果子进程在调用此函数之前就已退出,此函数会立刻返回。子进程使用的资源将被释放。

案例3

<?php$pid = pcntl_fork();if($pid == -1) {die('fork error');} else if ($pid) {pcntl_wait ($status);echo "parent \\n";} else {sleep(3);echo "child \\n";exit;}

上述代码,我们可以看到,父进程执行pcntl_wait时就已经挂起,直到等待3秒后输出child,子进程退出后。父进程继续执行,输出parent。

案例4

<?phpdefine('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]) {pcntl_waitpid($pids[$i], $status);echo "pernet \\n";} else {sleep(3);echo "child id:" . getmypid() . " \\n";exit;}}

上述代码,我们创建3个子进程,父进程分别挂起等待子进程结束后,输出parent。

案例5

<?phpdefine('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:57579child id:57581child id:57580parentparentparent

我们可以看到案例5的pcntl_waitpid函数放在了foreach中,foreach代码是在主进程中,也就是父进程的代码中。当执行foreach时,可能子进程已经全部执行完毕并退出。pcntl_waitpid会立刻返回,连续输出三个parent。
在子进程中,需通过exit来退出,不然会产生递归多进程,父进程中不需要exit,不然会中断多进程。

案例6

<?phpdefine('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);
//结果57641: success57641: success57641: success57641: success57641: success57642: success57642: success57642: success57642: success57642: success57643: success57643: success57643: success57643: success57643: success//test.log  日志内容57641 : 2018-02-02 15:55:48 : 157641 : 2018-02-02 15:55:48 : 257641 : 2018-02-02 15:55:48 : 357641 : 2018-02-02 15:55:48 : 457641 : 2018-02-02 15:55:48 : 557642 : 2018-02-02 15:55:48 : 157642 : 2018-02-02 15:55:48 : 257642 : 2018-02-02 15:55:48 : 357642 : 2018-02-02 15:55:48 : 457642 : 2018-02-02 15:55:48 : 557643 : 2018-02-02 15:55:48 : 157643 : 2018-02-02 15:55:48 : 257643 : 2018-02-02 15:55:48 : 357643 : 2018-02-02 15:55:48 : 457643 : 2018-02-02 15:55:48 : 5

我们可以看到三个子进程的pid,它们分别执行了5次,时间几乎是在同时。但是$num的值并没像我们期望的那样从1-15进行递增。子进程中的变量是各自独立的,互不影响。子进程会自动复制父进程空间里的变量。

案例7

<?phpdefine('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);
19923 : 2016-03-17 00:05:18 : 119923 : 2016-03-17 00:05:18 : 219923 : 2016-03-17 00:05:18 : 319923 : 2016-03-17 00:05:18 : 419923 : 2016-03-17 00:05:18 : 519924 : 2016-03-17 00:05:18 : 619924 : 2016-03-17 00:05:18 : 719924 : 2016-03-17 00:05:18 : 819924 : 2016-03-17 00:05:18 : 919924 : 2016-03-17 00:05:18 : 1019925 : 2016-03-17 00:05:18 : 1119925 : 2016-03-17 00:05:18 : 1219925 : 2016-03-17 00:05:18 : 1319925 : 2016-03-17 00:05:18 : 1419925 : 2016-03-17 00:05:18 : 15

这样我们就在进程间共享了$num的数据。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » PHP多进程学习(三)父进程与子进程的执行顺序,进程中共享数据