9

我有一些这样的代码,我想了解 fork 是如何工作的,但我对 declare(ticks=1). 当我把它放在第一行时,子进程完成后,将调用信号处理程序,这就是我想要的;但是当我删除它时,信号处理程序将永远不会被调用!所以,我想知道滴答声是如何影响信号处理的。

<?php
declare(ticks=1);
function sigHandler($signal)
{
    echo "a child exited\n";
}
pcntl_signal(SIGCHLD, sigHandler, false);
echo "this is " . posix_getpid() . PHP_EOL;
for($i=0; $i<3; $i++)
{
    $pid = pcntl_fork();
    if($pid == -1) 
    {   
        echo 'fork failed ' . PHP_EOL;
    }   
    else if($pid)
    {   
    }   
    else
    {   
        $pid = posix_getpid();
        echo 'child ' . $pid . ' ' . time() . PHP_EOL;
        sleep(rand(2,5));
        echo 'child ' . $pid . ' done ' . time() . PHP_EOL;
        exit(0);
    }   
}
do
{
    $pid = pcntl_wait($status); 
    echo 'child quit ' . $pid . PHP_EOL;
}while($pid > 0); 
echo 'parent done' . PHP_EOL;
?>
4

1 回答 1

10

小观察(请引用函数名):

pcntl_signal(SIGCHLD, 'sigHandler', false);

涉及两种不同的 API。

  • pcntl_wait() 调用一直阻塞,直到它收到来自内核的通知。
  • 中断处理是 PHP 解释器内部的一个事件循环。这是一个 hack 功能,从 PHP5.3 开始,有更好的方法来做到这一点 ~ pcntl_signal_dispatch()。
    • 要回答这个问题,声明滴答声就像打开手机铃声,否则您永远不会注意到来电。
    • PHP5.3 方法是更好的工程,更可控。
    • 大多数信号的默认信号处理程序是 sigignore,它接收中断并且什么都不做。由于您已经注册了用户处理程序,我怀疑它正在被使用。
    • 如果不直接设置,我永远无法发现刻度的默认值。
    • 将刻度设置为较小的值确实会使脚本运行速度变慢,但您需要进行大量处理和监视才能注意到这一点。我猜这是由于在堆栈中复制东西造成的执行成本更难以预测。
    • 如果没有声明滴答或 pcntl_signal_dispatch(),则永远不会接收到信号。如果您正在编写简单的网页,它会很快终止;这可能是最明智的政策。
    • declare ticks需要仔细测试,因为它的范围规则令人困惑。将它放在第一个脚本的开头最安全的方法,例如在 Perl 中使用 strict 。
于 2013-07-28T14:01:26.713 回答