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

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

直接上代码:


<?php
$pid = pcntl_fork();
$pid < 0 && die('fork failed....');

if($pid > 0)
{
    pcntl_signal(SIGINT, function($signo){
            echo "master caught a signal {$signo}" . PHP_EOL;
    }, false) ;

    $master_pid = posix_getpid();
    echo "(parent) parent process {$master_pid}, child process {$pid}" . PHP_EOL;

    while(1)
    {
            pcntl_signal_dispatch();
            $son_pid = pcntl_wait($status, WUNTRACED);
            pcntl_signal_dispatch();
            echo "wait was bread by signal..........." . PHP_EOL;
            if($son_pid > 0)  echo "child process $son_pid exited" . PHP_EOL;
            if($son_pid <= 0) echo "none........................." . PHP_EOL;
            sleep(1);
    }
}
else
{
    //子进程中信号管理请自行修改代码测试
    $son_pid = posix_getpid();
    $master_pid = posix_getppid();
    echo "(child)  child process {$son_pid}" . PHP_EOL;
    echo "send signal SIGINT to master" . PHP_EOL;
    posix_kill($master_pid, SIGINT);
    while(1);
    exit(0);
}


备注说明:

1、请自行注释第16、18行代码进行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、一次信号只会中断一个系统调用,并且只中断正在阻塞的系统调用,其它还没执行到系统调用则不受影响

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

8、2018-09-03最新调试发现问题,SEE: http://www.blogdaren.com/post-2468.html

#信号##系统调用#

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

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

发表评论:

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