PHP多进程编程之僵尸进程问题的理解

yipeiwu_com5年前PHP代码库

PHP多进程编程之僵尸进程问题的理解

使用pcntl_fork函数可以让PHP实现多进程并发或者异步处理的效果:https://www.jb51.net/article/125789.htm

那么问题是我们产生的进程需要去控制,而不能置之不理。最基本的方式就是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方法的解释:

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

原来有种方式可以防止进程成为僵尸进程,但是,官网给出的代码是这样子的:

$pid = pcntl_fork();
//父进程和子进程都会执行下面代码
if ($pid == -1) {
  //错误处理:创建子进程失败时返回-1.
   die('could not fork');
} else if ($pid) {
   //父进程会得到子进程号,所以这里是父进程执行的逻辑
   pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。
} else {
   //子进程得到的$pid为0, 所以这里是子进程执行的逻辑。
}

什么意思呢?就是父进程会等待子进程运行,等子进程运行结束之后,才会进行下一步,并且也会消除僵尸进程。但是这里又和我们的需求不符合了,我们的子进程为一个死循环的程序,不断的查找输出,更本没有结束的时候,并且我们需要的是异步处理而不是同步。但是这个方法可以用吗?其实当然可以。

在pcntl_wait的文档中是这么解释这个函数的:

wait函数刮起当前进程的执行直到一个子进程退出或接收到一个信号要求中断当前进程或调用一个信号处理函数。 如果一个子进程在调用此函数时已经退出(俗称僵尸进程),此函数立刻返回。子进程使用的所有系统资源将 被释放。关于wait在您系统上工作的详细规范请查看您系统的wait(2)手册。

我们发现,当这个函数发现子进程成为了僵尸进程就会释放僵尸进程的资源——前提是这个僵尸进程为这个父进程的子进程。那么我们就可以巧妙的利用这个方式让这些僵尸进程释放资源了,所以就有了如下代码:

 posix_kill(123, 9);
 pcntl_wait($status);

这样我们先使用kill干掉这个进程,这个进程就不会再运行了,但是这个进程成为了僵尸进程,占用着资源,我们下一句就执行一次pcntl_wait()让这些僵尸进程释放资源,这样,子进程才真正的被终止了,僵尸进程被消除了。

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

相关文章

php模拟post行为代码总结(POST方式不是绝对安全)

这里提供两种方法供选择:第一:手写代码。第二:利用HttpClient php类库   第一种方法: 复制代码 代码如下: <?PHP $flag = 0; //要post的数据...

由php中字符offset特征造成的绕过漏洞详解

php中的字符offset特性 php中的字符串存在一个非常有趣的特性,php中的字符串也可以像数组一样进行取值。 $test = "hello world"; echo $test...

php设计模式之单例模式实例分析

本文实例讲述了php设计模式之单例模式。分享给大家供大家参考。具体分析如下: 单例模式(职责模式): 简单的说,一个对象(在学习设计模式之前,需要比较了解面向对象思想)只负责一个特定的任...

yii 2.0中表单小部件的使用方法示例

前言 本文主要介绍的是关于yii 2.0中表单小部件使用的相关内容,分享出来供大家参考学习,下面来看看详细的介绍: 使用方法 首先创建model层,因为要使用表单小部件 所以要加载相应的...

php中使用base HTTP验证的方法

本文实例讲述了php中使用base HTTP验证的方法。分享给大家供大家参考。具体如下: function http_auth($un, $pw, $realm = "Secured...