php fork解密,php的pcntl_fork多进程小解

由于工作需要,今天研究了下php的多进程和多线程,今天先说一下多进程吧。主要说一样,多进程和多线程的区别;为什么他们都只能运行在php的cli模式下;以及多进程到底父进程和子进程是怎么工作的,什么顺序(先运行哪个进程)。结合我操作的实例简单总结一下,因为自己接触这方面也比较短,有什么错误或不足希望大家指正。

首先说一下为什么php要使用他们,很多phper可能一般都用不到这些,这取决于php本身作为web脚本的特性,他是阻断的、高并发的。所以有的人都认为php没有多进程和多线程,其实语言本地没有这样的区分,语言都是寄生在系统上的,系统支持,那么php做个扩展,就可以支持了啊。只是这些功能大家会不会用到而已,没有能不能之说。在一些特殊条件下,比如安全或完整性要求不是很高的采集,以及php做守护进程分发任务时用他们是比较好的。采集用多线程,汇总线程结果要比较for循环等快好几倍,守护进程用多进程,可以防止php直接做守护进程带来的内存溢出被kill掉。因为父进程可以只做分发,由子进程去做任务,这样子进程死了,也不会影响父进程。

2、多进程和多线程的区别。

我们应该知道php版本分一个nts和ts版本。即非线程安全和线程安全。这个其实比较好理解,大家可以查一下有很多资料。大家可以查一下php的几种运行模式的区别,对这方便理解有一定帮助。熟悉linux的应该比较容易理解进程的概念,很多php扩展也是考虑在linux多进程模式下编译开发的。所以php最好还是运行在linux比较好。多进程和多线程的作用都是一样的,都是类似与并行(当然不可能是真正的并行,可以说是快速轮询)来做一件或多件事情。这样会大大缩小程序执行的时间,多进程要更加消耗系统资源,但是更加安全稳定,因为某个子进程甚至父进程死掉,都不会影响其他进程,父进程先死掉,子进程会归属到1的父进程,运行完回收,子进程先死掉就更没问题了。而多线程更节省系统资源,但是一个线程崩溃,整个进程就挂掉。所以php这种等待返回,要根据程序执行结果操作的一般做法,可能不理解为什么要用这样不能保证安全的东西。这些东西当然是有他们的作用的。

3、为什么只能运行在cli模式下

这里我测试的是fpm-fcgi模式和cli模式,fpm-fcgi是一种常驻进程,并且可以请求复用此进程的模式。那么可想而知,如果子进程还在运行,但父进程请求结束处理新请求,就会乱了,而cli模式,php是以守护进程的方式运行,相当于一个请求一个守护进程,这样才能保证其对应关系。我是这样理解的。

4、使用

pcntl的扩展的安装就不说了,很简单,这里结合实例说一下pcntl_fork的运行方式

PHP

1

2

3

4

5

6

7

8

9

10

11

12

13

14<?php

echo$pid=pcntl_fork();

if($pid==-1){

die('could not fork');

}elseif(!$pid){

//这里是子进程

echo'-';

exit();

}else{

//这里是父进程

echo'A';

echo'B';

}

我用cli运行多次的结果是

adedfcd30ecdf370e106cf61745bd92d.png

$pid为0说明是子进程,因为pcntl_fork()的作用就是当程序运行到这里,就试图去创建一个子进程,如果创建成果,那么返回当前进程的子进程id,0表示当前进程没有子进程,那么其进程本身不就是子进程了,而如果有进程id,表示其有子进程,那么其不就是父进程。就好像是从这个位置其,下面的所有代码被复制到了另一个进程中执行一样,产生了一个子进程。但是从上面多次执行结果看,大部分情况下是先执行子进程的,这和我之前网上查的资料有些出入,而且这个顺序也不是固定的。但是我们发现倒数第三条,是先执行父进程,后执行的子进程,这时候子进程是有一定风险的,虽然子进程不会死,因为他会过继到1进程,但如果要等待子进程执行完可以这样:

PHP

1

2

3

4

5

6

7

8

9

10

11

12

13

14<?php

echo$pid=pcntl_fork();

if($pid==-1){

die('could not fork');

}elseif(!$pid){

//这里是子进程

echo'-';

exit();

}else{

//这里是父进程

echo'A';

pcntl_wait($status);//父进程执行到这里等等子进程执行完再执行

echo'B';

}

运行结果:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

210-31843AB[root@client60.test.com]# php index.php

0-31845AB[root@client60.test.com]# php index.php

0-31847AB[root@client60.test.com]# php index.php

0-31849AB[root@client60.test.com]# php index.php

0-31851AB[root@client60.test.com]# php index.php

0-31853AB[root@client60.test.com]# php index.php

0-31855AB[root@client60.test.com]# php index.php

31857A0-B[root@client60.test.com]# php index.php

0-31859AB[root@client60.test.com]# php index.php

0-31861AB[root@client60.test.com]# php index.php

0-31863AB[root@client60.test.com]# php index.php

0-31865AB[root@client60.test.com]# php index.php

0-31867AB[root@client60.test.com]# php index.php

0-31869AB[root@client60.test.com]# php index.php

0-31871AB[root@client60.test.com]# php index.php

0-31873AB[root@client60.test.com]# php index.php

0-31875AB[root@client60.test.com]# php index.php

0-31877AB[root@client60.test.com]# php index.php

0-31879AB[root@client60.test.com]# php index.php

0-31881AB[root@client60.test.com]# php index.php

0-31883AB[root@client60.test.com]# php index.php

我们发现,当然大部分是先执行了子进程,当然我认为可能是因为我写的子进程的操作太过简单,所以先输出了子进程的执行结果页不一定,但是这一条

131857A0-B[root@client60.test.com]# php index.php

就是我们想要的结果了,其他都没有问题,因为都是先执行的子进程,而这条是先执行了父进程,走到输出A就等子进程执行完才执行的下面的。所以这就是

PHP

1pcntl_wait($status)

的作用。

好了,基本就是这些了。至于进程间或线程间的通信,可以利用类似共享内存变量等的来做。具体情况具体对待吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值