• pcntl之pcntl_signal_dispatch


    PHP的pcntl扩展提供了信号处理的功能,利用它可以让PHP来接管信号的处理,在开发服务器端守护进程方面,信号处理至关重要。

    函数原型

    bool pcntl_signal(int $signo ,callback $handler [,bool $restart_syscalls=true])

    第一个参数是信号ID 
    第二个参数是信号发生时回调的PHP函数。 
    第三个参数是是否restart,是否重新注册此信号。这个参数如果为false,那此信号只注册处理一次。

    pcntl_signal的实现

    1.  
      <?php
    2.  
      //信号处理需要注册ticks才能生效,这里务必注意
    3.  
      //PHP5.4以上版本就不再依赖ticks了
    4.  
      declare(ticks = 1);
    5.  
      function sig_handler($signo){
    6.  
      switch ($signo) {
    7.  
      case SIGUSR1: echo "SIGUSR1 "; break;
    8.  
      case SIGUSR2: echo "SIGUSR2 "; break;
    9.  
      default: echo "unknow"; break;
    10.  
      }
    11.  
      }
    12.  
      //安装信号触发器器
    13.  
      pcntl_signal(SIGUSR1, "sig_handler");
    14.  
      pcntl_signal(SIGUSR2, "sig_handler");
    15.  
      //向当前进程发送SIGUSR1信号
    16.  
      posix_kill(posix_getpid(), SIGUSR1);
    17.  
      posix_kill(posix_getpid(), SIGUSR2);
    18.  
      ?>

    执行此代码会在终端输出你想要的结果,其实官方的pcntl_signal性能极差,主要是PHP的函数无法直接注册到操作系统信号设置中,所以pcntl信号需要依赖tick机制来完成。 
    pcntl_signal的实现原理是,触发信号后先将信号加入一个队列中。然后在PHP的ticks回调函数中不断检查是否有信号,如果有信号就执行PHP中指定的回调函数,如果没有则跳出函数。 
    ticks=1表示每执行1行PHP代码就回调此函数。实际上大部分时间都没有信号产生,但ticks的函数一直会执行。 
    比较好的做法是去掉ticks,转而使用pcntl_signal_dispatch,在代码循环中自行处理信号。

    pcntl_signal_dispatch的实现

    1.  
      <?php
    2.  
      // 定义一个处理器,接收到SIGINT信号后只输出一行信息
    3.  
      function signalHandler($signo) {
    4.  
      switch ($signo) {
    5.  
      case SIGUSR1: echo "SIGUSR1 "; break;
    6.  
      case SIGUSR2: echo "SIGUSR2 "; break;
    7.  
      default: echo "unknow"; break;
    8.  
      }
    9.  
      }
    10.  
      //安装信号触发器器
    11.  
      pcntl_signal(SIGINT, 'signalHandler');
    12.  
      while (true) {
    13.  
      sleep(1);
    14.  
      posix_kill(posix_getpid(), SIGUSR1);
    15.  
      pcntl_signal_dispatch(); //接收到信号时,调用注册的signalHandler()
    16.  
      }

    实战:用信号来处理函数超时

      1.  
        <?php
      2.  
        function a(){
      3.  
        sleep(10);
      4.  
        echo "OK ";
      5.  
        }
      6.  
        function b(){
      7.  
        echo "Stop ";
      8.  
        }
      9.  
        function c(){
      10.  
        usleep(100000);
      11.  
        }
      12.  
        //信号处理代码
      13.  
        function sig(){
      14.  
        throw new Exception;
      15.  
        }
      16.  
        try{
      17.  
        pcntl_alarm(2); //设定超时后触发的信号
      18.  
        pcntl_signal(SIGALRM, "sig");
      19.  
        pcntl_signal_dispatch();
      20.  
        a();
      21.  
        pcntl_alarm(0);
      22.  
        }catch(Exception $e){
      23.  
        echo "timeout ";
      24.  
        }
      25.  
        b();
      26.  
        a(); //等待十秒后完成
      27.  
        b();
  • 相关阅读:
    10.2 查找同一组或分区中行之间的差
    8.7 确定当前记录和下一条记录之间相差的天数
    8.6 计算一年中周内各日期的次数
    8.5 确定两个日期之间的秒、分、小时数
    8.4 确定两个日期之间的月份数或年数
    8.2 计算两个日期之间的天数
    8.3 确定两个日期之间的工作日数目
    8.1 加减日、月、年
    7.13 计算不包含最大值和最小值的均值
    第3章 Python的数据类型 第3.1节 功能强大的 Python序列概述
  • 原文地址:https://www.cnblogs.com/liliuguang/p/12599804.html
Copyright © 2020-2023  润新知