• PHP进程通信基础——信号


    PHP进程通信基础——信号

    PHP进程通信基础——信号

    使用信号通信。可以使用kill -l 来查看当前系统的信号类型。
    每个信号所代表的的详细含义,请查看我的这篇博客:http://www.cnblogs.com/roverliang/p/6050964.html
    使用信号的时候可以通过php --version 来查看当前PHP的版本。已决定使用哪种方式来进行进程间的信号通信。

    [root@roverliang ipc]# php --version

    PHP 5.6.24 (cli) (built: Aug 15 2016 19:14:02)
    Copyright (c) 1997-2016 The PHP Group
    Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies

    使用pcntl_signal_dispatch 函数 需要PHP 版本(PHP 5 >= 5.3.0, PHP 7)
    如果PHP版本小于5.3.一些大公司可能会低于这个版本。这个时候会使用 declare(ticks=1),意思为每执行一条低级指令,
    就会去检测是否出现该信号。详细的介绍可以查看官网的介绍:http://php.net/manual/zh/control-structures.declare.php

    官网解释如下:Tick(时钟周期)是一个在 declare 代码段中解释器每执行 N 条可计时的低级语句就会发生的事件。N 的值是在 declare 中的 directive 部分用 ticks=N 来指定的。

    那么什么是低级语句呢:如下代码所示:

        for ($i = 0; $i < 3; $i++) {
    echo $i.PHP_EOL;
    }

    那么这个for 循环中就含有三条低级指令。每输出一条$i。就会去检测下是否发生了已注册的事件,可想而知,这样效率是比较低的。所以如果检测到自己的PHP大于等于5.3 。就使用pcntl_singal_dispath 来进行信号派送。

    主进程在启动的时候注册一些信号处理函数。

    /**
    * @param $signal 信号
    */

    function signalHandal($signal)
    {
    switch ($signal) {
    case SIGINT:
    //do something
    break;
    case SIGHUP:
    //do something
    break;
    default :
    //do something
    break;
    }
    }

    然后将信号处理器与信号处理函数绑定:

    //根据不同的信号,安装不同的信号处理器
    pcntl_signal(SIGINT, 'signalHandal');
    pcntl_signal(SIGHUP, 'signalHandal');
    pcntl_signal(SIGUSR1, 'signalHandla');

    在子进程监听信号,如果出现该信号,就调用预安装的信号处理函数

    //分配信号。
    pcntl_signal_dispatch($signal);

    我们来整理下思路:
    1、定义信号发生所需要处理事件的函数
    2、将信号和信号处理函数绑定,称为信号安装。
    3、信号监听或者分发,出现信号调用已安装的信号。

    理解好上面的信号概念,我们来看一个demo:

    <?php
    $parentpid = posix_getpid();
    echo "parent progress pid:{$parentpid} ";

    //定义一个信号处理函数

    function sighandler($signal) {
    if ($signal == SIGINT) {
    $pid = getmypid();
    exit("{$pid} process, Killed!".PHP_EOL);
    }
    }

    //php version < 5.3 .每执行一条低级指令,就检查一次是否出现该信号。效率损耗很大。
    //declare(ticks=1);
    $child_list = [];
    //注册一个信号处理器。当发出该信号的时候对调用已定义的函数
    pcntl_signal(SIGINT, 'sighandler');



    for($i = 0; $i < 3; $i++) {
    $pid = pcntl_fork();
    if ($pid == 0) {
    //子进程
    while (true) {
    //调用已安装的信号信号处理器,为了检测是否有新的信号等待dispatching
    pcntl_signal_dispatch();
    echo "I am child: ".getmypid(). " and i am running !".PHP_EOL;
    sleep(rand(1,3));
    }
    } elseif($pid > 0) {
    $child_list[] = $pid;
    } else {
    die('fork fail!'.PHP_EOL);
    }
    }

    sleep(5);
    foreach ($child_list as $key => $pid) {
    posix_kill($pid, SIGINT);
    }

    sleep(2);
    echo "{$parentpid} parent is end".PHP_EOL;
  • 相关阅读:
    codesmith
    moment.js
    select2
    Lodash js数据操作库
    angular.js
    vue.js
    axios.js
    RoutePrefix和Route 路由前缀
    Tuple元组 C#
    ningx访问日志切割
  • 原文地址:https://www.cnblogs.com/roverliang/p/6249002.html
Copyright © 2020-2023  润新知