欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

PHP进程信号处理

程序员文章站 2023-08-21 08:46:52
PHP进程信号处理 php有一组进程控制函数PCNTL,使得php能在*nix系统中实现跟c一样的创建子进程、使用exec函数执行程序、处理信号等功能。 注意:pcntl这个扩展仅在cli/cgi模式下可用。mod_php和php-fpm中不可以使用。在web server环境中不要使用这组函数,因 ......

php进程信号处理

  php有一组进程控制函数pcntl,使得php能在*nix系统中实现跟c一样的创建子进程、使用exec函数执行程序、处理信号等功能。

注意:pcntl这个扩展仅在cli/cgi模式下可用。mod_php和php-fpm中不可以使用。在web server环境中不要使用这组函数,因为会导致不可预料的结果。另,windows作为非类unix系统,没有这些函数。

  pcntl 使用ticks来作为信号处理机制(signal handle callback mechanism),可以最小程度地降低处理异步事件时的负载。何谓ticks?tick 是一个在代码段中解释器每执行 n 条低级语句就会发生的事件,这个代码段需要通过declare来指定。

下面是一个隔5秒发送一个sigalrm信号,并由signal_handler函数获取,然后打印一个“caught sigalrm”的例子:

<?php   
        declare(ticks = 1);   
      
        function signal_handler($signal) {   
            print "caught sigalrm/n";   
            pcntl_alarm(5);   
        }   
      
        pcntl_signal(sigalrm, "signal_handler", true);   
        pcntl_alarm(5);   
      
        while(true){
​
        }
      
    ?>

 

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

pcntl_signal_dispatch的实现

<?php
// 定义一个处理器,接收到sigint信号后只输出一行信息
function signalhandler($signo) {
    switch ($signo) {
        case sigusr1: echo "sigusr1\n"; break;
        case sigusr2: echo "sigusr2\n"; break;
        default:      echo "unknow";    break;
    }
}
​
//安装信号触发器器
pcntl_signal(sigint, 'signalhandler');
while (true) {
    sleep(1);
    posix_kill(posix_getpid(), sigusr1);///向当前进程发送sigusr1信号
    pcntl_signal_dispatch(); //接收到信号时,调用注册的signalhandler()
}

 

pcntl的函数:

信号处理

 

int pcntl_alarm ( int $seconds )

设置一个$seconds秒后发送sigalrm信号的计数器

 

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

为$signo设置一个处理该信号的回调函数

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

注意:每次对 pcntl_alarm()的调用都会取消之前设置的alarm信号和sleep()函数。