linux下php多进程编程

转载地址:

http://blog.csdn.net/wzllai/article/details/8257091

   php在很多情况用在web开发中,通常情况下一次请求对应一个php进程,进程执行完返回数据销毁执行过程中的中间变量代码,在一些perfork类型的的sapi中,它又会等待下一个请求过来重新初始化执行环境、执行脚本,已经执行完成后的清理工作。但在如命令行下有时候一个进程满足不了需求,比如微博的异步发送,如果是用php脚本处理的话,脚本需要从发送队列中取数据,然后对数据进行处理,一个进程显然太慢,解决这种问题可以用php自带的popen、exect之类的函数,也可以用php多进程编程来解决。

  

  php的多进程管理需要pcntlposix扩展,在官方手册中:

POSIX functions are enabled by default. You can disable POSIX-like functions with --disable-posix 。

Process Control support in PHP is not enabled by default. You have to compile the CGI or CLI version of PHP with --enable-pcntl configuration option when compiling PHP to enable Process Control support.

因为posix协议是针对unix系的,window下就不考虑了。下面用这两个扩展中的函数写一个多进程的daemon进程。

  1. <?php  
  2. $max     = 6;  
  3. $current = 0;  
  4. pcntl_signal(SIGCHLD, "reduce_current");  
  5.   
  6. /* 
  7.  * signal callback function  
  8. */  
  9. function reduce_current($signal)  
  10. {  
  11.     global $current;  
  12.     if ($signal === SIGCHLD) {  
  13.         $current--;  
  14.     }  
  15. }  
  16.   
  17. // become a daemon  
  18. if (($pid = pcntl_fork()) === -1) {  
  19.     die("fork error");  
  20. elseif ($pid) {  
  21.     exit;  
  22. else {  
  23.     if (posix_setsid() === -1)  
  24.         die("setsid error");  
  25.   
  26.     if (($pid = pcntl_fork()) === -1)   
  27.         die("fork error");  
  28.     elseif($pid)   
  29.         exit;  
  30.   
  31. }  
  32.   
  33. while(1) {  
  34.     $current++;  
  35.     if (($pid = pcntl_fork()) === -1) {  
  36.         //log and  exit  
  37.   
  38.     } elseif ($pid) {  
  39.         //father process  
  40.         if ($current >= $max ) {  
  41.             //blocking  
  42.             if(pcntl_wait($status) === -1) {  
  43.                 //log or exit  
  44.             }  
  45.         }  
  46.   
  47.     } else {  
  48.         //child process   
  49.         //do something repalce sleep  
  50.         sleep(3);  
  51.         exit;  
  52.     }  
  53. }  

   代码中规定脚本最大可以fork出6个进程,但数据达到6个后,会调用pcntl_warit使父进程挂起。当子进程执行完自己的任务(此处以sleep 3 秒代替)后退出时,父进程通过 捕获子进程退出状态,通过pcntl_signal 注册的的回调函数使其子进程数量减1,然后又可以继续fork子进程。如图中,父进程通过两次fork变成一个daemon进程,其父进程id为1(即init进程),其6个子进程的ppid与它的pid一样,都是918。