关于pcntl_wait与信号中断触发以及pcntl_signal_dispatch的问题
直接上代码:
<?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 )原创,转载请保留文章出处。