关于pcntl_wait与信号中断触发以及pcntl_signal_dispatch的问题

blogdaren 2018-03-26 抢沙发 524人次

直接贴一段代码:

<?php
function stopAll($sig){
        echo "master caught a signal $sig" . PHP_EOL;
}

$pid = pcntl_fork();

if($pid > 0)
{
        $master_id = posix_getpid();
        echo "(parent) parent process {$master_id}, child process {$pid}" . PHP_EOL;
        pcntl_signal(SIGINT, 'stopAll') ;
        $epid = pcntl_wait($status, WUNTRACED);
        echo "======================" . PHP_EOL;
        pcntl_signal_dispatch();

        if($epid > 0) echo "child process $epid exit" . PHP_EOL;
}
else
{
        $master_id = posix_getppid();
        $id = posix_getpid();
        echo "(child) child process {$id}" . PHP_EOL;
        sleep(3);
        echo "send signal to master" . PHP_EOL;
        posix_kill($master_id, SIGINT);
}

备注说明:

1. 请自行注释第15行代码进行DEMO调试。

2. pcntl_wait其实就是wait系统调用,是可以被信号打断的,当信号到来后pcntl_wait会立刻返回。同理,sleep也是系统调用,也可以被信号打断停止睡眠立刻返回。所以在调用pcntl_wait或者sleep之后,再调用pcntl_signal_dispatch函数,如果收到了信号,那么pcntl_signal_dispatch函数会立刻被执行。

3. 信号有个作用,会打断系统调用,让系统调用立刻返回,比如read、poll等都是系统调用。
    sleep也是系统调用,所以即使是sleep(100),当信号发生时sleep会立刻返回,实际不会sleep 100秒。while循环里利用系统调用等待信号是一个很常用的做法,例如主进程监控子进程退出事件可以用wait系统调用,下一句紧接着是pcntl_signal_dispatch,这样既可以监听到子进程退出,也可以监听到其它信号并及时处理。

4. 信号回调是不会自己自动执行的,要么主动声明declare(ticks=1),要么主动调用pcntl_signal_dispatch检查信号以执行信号回调处理函数,推荐高性能pcntl_singal_dispatch。

5. pcntl_signal_dispatch函数的作用:检测信号队列里是否有信号发生,如果有,则执行进程绑定的信号处理回调函数。

6. 有关补充验证,SEE: http://wenda.workerman.net/?/article/18

版权声明:除非注明,本文由( blogdaren )原创,转载请保留文章出处。

本文链接:关于pcntl_wait与信号中断触发以及pcntl_signal_dispatch的问题

发表评论:

您的昵称:
电子邮件:
个人主页: