经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » PHP » 查看文章
PHP进程信号处理
来源:cnblogs  作者:Martini  时间:2018/9/27 16:49:57  对本文有异议

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”的例子:

  1. <?php
  2. declare(ticks = 1);
  3. function signal_handler($signal) {
  4. print "Caught SIGALRM/n";
  5. pcntl_alarm(5);
  6. }
  7. pcntl_signal(SIGALRM, "signal_handler", true);
  8. pcntl_alarm(5);
  9. while(true){
  10. ?
  11. }
  12. ?>

 

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

pcntl_signal_dispatch的实现

  1. <?php
  2. // 定义一个处理器,接收到SIGINT信号后只输出一行信息
  3. function signalHandler($signo) {
  4. switch ($signo) {
  5. case SIGUSR1: echo "SIGUSR1\n"; break;
  6. case SIGUSR2: echo "SIGUSR2\n"; break;
  7. default: echo "unknow"; break;
  8. }
  9. }
  10. ?
  11. //安装信号触发器器
  12. pcntl_signal(SIGINT, 'signalHandler');
  13. while (true) {
  14. sleep(1);
  15. posix_kill(posix_getpid(), SIGUSR1);///向当前进程发送SIGUSR1信号
  16. pcntl_signal_dispatch(); //接收到信号时,调用注册的signalHandler()
  17. }

 

PCNTL的函数:

信号处理

 

  1. int pcntl_alarm ( int $seconds )

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

 

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

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

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

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

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

  1. <?php
  2. declare(ticks = 1);
  3. function signal_handler($signal) {
  4. print "Caught SIGALRM/n";
  5. pcntl_alarm(5);
  6. }
  7. pcntl_signal(SIGALRM, "signal_handler", true);
  8. pcntl_alarm(5);
  9. for(;;) {
  10. }
  11. ?>

 

执行程序

  1. void pcntl_exec ( string $path [, array $args [, array $envs ]] )

在当前的进程空间中执行指定程序,类似于c中的exec族函数。所谓当前空间,即载入指定程序的代码覆盖掉当前进程的空间,执行完该程序进程即结束。

  1. <?php
  2. $dir = '/home/test/';
  3. $cmd = 'ls';
  4. $option = '-l';
  5. $pathtobin = '/bin/ls';
  6. $arg = array($cmd, $option, $dir);
  7. pcntl_exec($pathtobin, $arg);
  8. echo '123'; //不会执行到该行
  9. ?>

 

创建进程

  1. int pcntl_fork ( void ) 为当前进程创建一个子进程
  2. int pcntl_wait ( int &$status [, int ?$options ] ) 阻塞当前进程,只到当前进程的一个子进程退出或者收到一个结束当前进程的信号。
  3. int pcntl_waitpid ( int $pid , int &$status [, int $options ] ) 功能同pcntl_wait,区别为waitpid为等待指定pid的子进程。当pid为-1pcntl_waitpidpcntl_wait一样。

 

在 pcntl_wait和pcntl_waitpid两个函数中的$status中存了子进程的状态信息,这个参数可以用于 pcntl_wifexited、pcntl_wifstopped、pcntl_wifsignaled、pcntl_wexitstatus、 pcntl_wtermsig、pcntl_wstopsig、pcntl_waitpid这些函数。

举个例子??

  1. <?php
  2. $pid = pcntl_fork();
  3. if($pid) {
  4. pcntl_wait($status);
  5. $id = getmypid();
  6. echo "parent process,pid {$id}, child pid {$pid}/n";
  7. } else {
  8. $id = getmypid();
  9. echo "child process,pid {$id}/n";
  10. sleep(2);
  11. }
  12. ?>

子进程在输出child process等字样之后sleep了2秒才结束,而父进程阻塞着直到子进程退出之后才继续运行。

 

进程优先级

  1. int pcntl_getpriority ([ int $pid [, int $process_identifier ]] ) 取得进程的优先级,即nice值,默认为0。不同的系统类型以及内核版本下 优先级可能不同(手册中为-2020
  2. bool pcntl_setpriority ( int $priority [, int $pid [, int $process_identifier ]] ) 设置进程的优先级

 

 

参考资料PHP进程信号处理

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号