php实验结果与分析,php的多进程实验分析

## php的多进程实验分析

>[tip] 由于时间久远,本文不再具有参考性,请参阅更为易读新文章:[进程 · php笔记 · 看云](https://www.kancloud.cn/xiak/php-node/785180)

pcntl_fork — 在当前进程当前位置产生分支(子进程)。译注:fork是创建了一个子进程,父进程和子进程 都从fork的位置开始向下继续执行,不同的是父进程执行过程中,得到的fork返回值为子进程 号,而子进程得到的是0。

```php

fwrite(STDOUT, "stat>" . PHP_EOL.PHP_EOL);

$count = 3;

for ($i = 0; $i < $count; $i++) {

$pid = pcntl_fork();

if($pid == -1) {

fwrite(STDOUT, "Could not fork worker {$i}" . PHP_EOL);

die();

}

else if(!$pid) {

fun($i, $count);

// 如果不使用下面的方式退出,将会出现什么呢,经测试,下面是我们得出的结果。

// break;

// exit;

} else {

fwrite(STDOUT, "父进程 " . $i . PHP_EOL);

}

}

function fun($i, $count)

{

// global $num;

$num = $i;

$jc = exec('echo $$');

$time = date('Y-m-d H:i:s');

fwrite(STDOUT, "进程:$jc 计数:$num - $count 时间:$time" . PHP_EOL);

fwrite(STDOUT, "start > " . date('Y-m-d H:i:s') . PHP_EOL);

fwrite(STDOUT, "~ 3s ~" . PHP_EOL);

sleep(3);

fwrite(STDOUT, "enddd $i < " . date('Y-m-d H:i:s') . PHP_EOL.PHP_EOL);

}

```

父进程循环 从0开始 3次创建3个子进程 产生下面第一部分

i = 0/1/2 结束循环

子0进程下面的循环 从1开始循环 能循环2次 创建2个子进程 产生下面第二部分(由第一子进程产生) 和 第三部分(由第二子进程产生)

子1进程下面的循环 从2开始循环 能循环1次 创建1个子进程 产生下面第四部分

子2进程下面的循环 没有循环 退出了(什么都没做)

由此分析可见PHP的这个子进程机制的特点:

继承父进程的“运行上下文”即变量和环境都是直接继承了,并且各个子进程相互,不受影响。

~~~

[root@iZ28yn5lehbZ x]# x=sf php d3.php

stat>

父进程 0

父进程 1

父进程 2

进程:25608 计数:0 - 3 时间:2016-08-15 08:35:47

start > 2016-08-15 08:35:47

~ 3s ~

进程:25610 计数:2 - 3 时间:2016-08-15 08:35:47

start > 2016-08-15 08:35:47

~ 3s ~

进程:25611 计数:1 - 3 时间:2016-08-15 08:35:47

start > 2016-08-15 08:35:47

~ 3s ~

enddd 1 < 2016-08-15 08:35:50

enddd 2 < 2016-08-15 08:35:53

enddd 0 < 2016-08-15 08:35:50

父进程 1

父进程 2

进程:25643 计数:1 - 3 时间:2016-08-15 08:35:50

start > 2016-08-15 08:35:50

~ 3s ~

进程:25644 计数:2 - 3 时间:2016-08-15 08:35:50

start > 2016-08-15 08:35:50

~ 3s ~

enddd 1 < 2016-08-15 08:35:53

enddd 2 < 2016-08-15 08:35:53

父进程 2

进程:25646 计数:2 - 3 时间:2016-08-15 08:35:50

start > 2016-08-15 08:35:50

~ 3s ~

enddd 2 < 2016-08-15 08:35:50

父进程 2

进程:25663 计数:2 - 3 时间:2016-08-15 08:35:53

start > 2016-08-15 08:35:53

~ 3s ~

enddd 2 < 2016-08-15 08:35:56

~~~

php获取子进程ID

```

$jc = exec('echo $$'); // 这方式获取的不是当前PHP脚本执行的进程ID

$child_id = getmypid(); // 这个才是当前PHP脚本执行的进程ID

```

参见:https://segmentfault.com/q/1010000004634861

```

父进程:17488 字进程:17489 计数:0

父进程:17488 字进程:17490 计数:1

进程:17489 计数:0 - 3 时间:2016-08-15 16:55:22

start > 2016-08-15 16:55:22

~ 3s ~

父进程:17488 字进程:17491 计数:2

进程:17490 计数:1 - 3 时间:2016-08-15 16:55:22

start > 2016-08-15 16:55:22

~ 3s ~

进程:17491 计数:2 - 3 时间:2016-08-15 16:55:22

start > 2016-08-15 16:55:22

~ 3s ~

[root@iZ28yn5lehbZ x]# enddd 0 < 2016-08-15 16:55:25

enddd 1 < 2016-08-15 16:55:25

enddd 2 < 2016-08-15 16:55:25

```

上面这个父进程执行部分是否先输出来,有时并无实际规律,理论上和实际上不一样,原因是可能需要考虑进程在CPU资源分配使用上面。(但好像父进程 计数:0永远在第一,也就是说在这个开辟子进程的结构中,父进程是首次执行的。)

```

$status = '';

$pid = pcntl_fork();

//父进程和子进程都会执行下面代码

if ($pid == -1) {

//错误处理:创建子进程失败时返回-1.

die('could not fork');

} else if ($pid) {

//父进程会得到子进程号,所以这里是父进程执行的逻辑

// pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。

fwrite(STDOUT, "父进程" . PHP_EOL);

} else {

//子进程得到的$pid为0, 所以这里是子进程执行的逻辑。

fwrite(STDOUT, "子进程" . PHP_EOL);

}

```

**分析**

1. 父进程执行完毕就退出了,但是这个退出不会结束可能还没执行完成的子进程,也就是说子进程会变成僵尸进程,这并不像结束了ssh就结束了bash,就结束了我们的脚本那样。(这个也确实是要成为僵尸进程,不然孩子刚生出来还没玩够就要死了)

2. 输出顺序为:

父进程

子进程

如果将pcntl_wait这一行注释掉,输出顺序就为

子进程

父进程

**测试:**

父进程和子进程 都从fork的位置开始向下继续执行,所以这个硬要说规律也不好说,这个是CPU指令执行资源的事了。

![](https://box.kancloud.cn/2016-08-17_57b4207ea01ac.png)

* * * * *

### 扩展

[从 0 到 1 优雅的实现PHP多进程管理](https://mp.weixin.qq.com/s/lbGCQu7zkKUfPhFMFbHooQ)

[TIGERB/naruto: An object-oriented multi process manager for PHP](https://github.com/TIGERB/naruto)

* * * * *

last update:2017-12-18 14:55:26

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值