在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
上一篇说到了使用pcntl_fork函数可以让PHP实现多进程并发或者异步处理的效果。那么问题是我们产生的进程需要去控制,而不能置之不理。最基本的方式就是fork进程和杀死进程。 通过利用pcntl_fork函数,我们已经有了新的子进程,而子进程接下来完成我们需要处理的内容,那么我们就暂且叫做service()吧,而且我们需要很多个service()进行处理,再次参照我们之前的需求,父进程需要一直循环读取配置文件,等待文件发生改变。通过对pcntl_fork的方式,很容易我们就可以写出如下代码: $res = config(); //kill进程 for($i = 0; $i < $res[sum]; $i++) { $pid = pcntl_fork(); if ($pid == 0) { service(); return; } } 代码中注释的地方我们需要在配置文件中发生改变的时候杀死进程,杀死进程的的方式很简单,可以使用kill命令直接杀死,比如(假设pid为123): 1 kill 123 但是我们发现,使用这个杀死进程的方式并没有真正的把进程杀死,这个子进程被杀死后还占用这个进程的资源,我们成为僵尸进程,僵尸进程是使用kill命令无法杀死的。想要解决这个问题,我们能做的只有两种方式。 1. shutdown 2. 杀死该进程的父进程。 但是这两种方法都不行,因为这个程序的目的是监控常驻在服务器内,服务器不能关闭,并且父进程也不能被干掉。这时候我们看到了官方文档对于fork方法的解释: 1 pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。 原来有种方式可以防止进程成为僵尸进程,但是,官网给出的代码是这样子的: 1 $pid = pcntl_fork(); 2 //父进程和子进程都会执行下面代码 3 if ($pid == -1) { 4 //错误处理:创建子进程失败时返回-1. 5 die('could not fork'); 6 } else if ($pid) { 7 //父进程会得到子进程号,所以这里是父进程执行的逻辑 8 pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。 9 } else { 10 //子进程得到的$pid为0, 所以这里是子进程执行的逻辑。 11 } 什么意思呢?就是父进程会等待子进程运行,等子进程运行结束之后,才会进行下一步,并且也会消除僵尸进程。但是这里又和我们的需求不符合了,我们的子进程为一个死循环的程序,不断的查找输出,更本没有结束的时候,并且我们需要的是异步处理而不是同步。但是这个方法可以用吗?其实当然可以。 在pcntl_wait的文档中是这么解释这个函数的:
我们发现,当这个函数发现子进程成为了僵尸进程就会释放僵尸进程的资源——前提是这个僵尸进程为这个父进程的子进程。那么我们就可以巧妙的利用这个方式让这些僵尸进程释放资源了,所以就有了如下代码: 1 posix_kill(123, 9); 2 pcntl_wait($status); 这样我们先使用kill干掉这个进程,这个进程就不会再运行了,但是这个进程成为了僵尸进程,占用着资源,我们下一句就执行一次pcntl_wait()让这些僵尸进程释放资源,这样,子进程才真正的被终止了,僵尸进程被消除了。 |
2022-08-17
2022-11-06
2022-08-17
2022-08-14
2022-07-18
请发表评论