当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP 进程池与轮询调度算法实现多任务的示例代码

发布:smiling 来源: PHP粉丝网  添加日期:2022-01-24 14:07:53 浏览: 评论:0 

这篇文章主要介绍了PHP 进程池与轮询调度算法实现多任务的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。

phper 请了解进程调度策略,CPU 时间片,进程控制【创建,销毁,回收,进程信号】与及进程运行流程和基本的进程组,信号中断原理,以及进程之间的关系。

关于进程的更多内容可参考本人前面撸过的文章或是百度了解。

进程的通信:

匿名管道,命名管道,消息队列,内存共享,socketpair 请自行撸代码测试哦

进程的调度算法:

轮询,随机分发,计分板等策略或是搞个优先极或是队列,或是堆栈等基本的算法【自己去发挥哦】

进程池:

撸过 tcp 的话应该知道要能处理多个客户端,就得用 IO 复用技术【事件多路分发器】或是多进程以及多线程,每来一个客户端就 fork 一个进程或是线程,那样的话上下文切换成本特别高,所以咱们先创建好一组进程【进程池】,等客户端连接上来的时候,通过某种算法【我们用的轮询】来选择某个进程投递任务来干活,这样的话就不用创建又销毁来回折腾了,提升它的效率。下面是 PHP 代码版本的实现

  1. <?php 
  2. /** 
  3.  * Created by PhpStorm. 
  4.  * User: 1655664358@qq.com 
  5.  * Date: 2019/1/12 
  6.  * Time: 16:18 
  7.  */ 
  8.  
  9. $flag = 1; 
  10.  
  11. class process 
  12. { 
  13.  public $pid; 
  14.  public $name; 
  15.  public $file; 
  16.  public $num; 
  17. } 
  18. class instance 
  19. { 
  20.  public $processIdx; 
  21.  public $proc = []; 
  22.  public $processNum; 
  23. } 
  24. function sigHandler($sigNo) 
  25. { 
  26.  global $flag; 
  27.  $flag = 0; 
  28.  echo "信号中断处理".PHP_EOL; 
  29. } 
  30. function processPool(instance &$instance,$num) 
  31. { 
  32.  
  33.  if (!$instance||$num==0){ 
  34.   fprintf(STDERR,"%s","参数错误"); 
  35.   return 1; 
  36.  } 
  37.  $instance->processIdx = 0; 
  38.  $instance->processNum = $num; 
  39.  
  40.  pcntl_signal(SIGINT,'sigHandler'); 
  41.  pcntl_signal(SIGTERM,'sigHandler'); 
  42.  
  43.  $process = new process(); 
  44.  for ($i=1;$i<=$num;$i++){ 
  45.   $instance->proc[$i] = clone $process; 
  46.   $instance->proc[$i]->file = $i; 
  47.   $instance->proc[$i]->pid = pcntl_fork(); 
  48.   $instance->processIdx = $i; 
  49.   if ($instance->proc[$i]->pid<0){ 
  50.    exit("进程创建失败"); 
  51.   } 
  52.   else if ($instance->proc[$i]->pid>0){ 
  53.    //nothing 
  54.    continue; 
  55.   }else{ 
  56.  
  57.    worker($instance); 
  58.   } 
  59.  } 
  60.  master($instance); 
  61.  $exitProcess= []; 
  62.  while (1){ 
  63.   for ($i=1;$i<=$num;$i++){ 
  64.   //非阻塞方式回收子进程 
  65.    pcntl_waitpid($instance->proc[$i]->pid,$status,WNOHANG); 
  66.    if ($status){ 
  67.     $exitProcess[] = $instance->proc[$i]->pid; 
  68.     fwrite(STDOUT,"worker#".$instance->proc[$i]->pid."-".$status,30); 
  69.    } 
  70.   } 
  71.   if (count($exitProcess)==$instance->processNum){ 
  72.    exit(0); 
  73.   } 
  74.   usleep(1000); 
  75.  
  76.  } 
  77.  
  78. } 
  79. //简单的轮询算法 自己可以用队列,随机,链表,栈链,二叉树啥的折腾 
  80. function roundRobin(&$instance,$roll) 
  81. { 
  82.  /** @var instance $instance */ 
  83.  return $instance->proc[$roll%$instance->processNum+1]; 
  84. } 
  85.  
  86. function master(&$instance) 
  87. { 
  88.  
  89.  /** @var instance $instance */ 
  90.  fprintf(STDOUT,"master 进程 %d\n",$instance->processIdx); 
  91.  global $flag; 
  92.  $roll = 0; 
  93.  while ($flag){ 
  94.   pcntl_signal_dispatch(); 
  95.   /** @var process $process */ 
  96.   $process = roundRobin($instance,$roll++); 
  97.   echo "轮询的进程:".$process->pid.PHP_EOL; 
  98.   $file = $process->file; 
  99.   posix_mkfifo($file,0666); 
  100.   $fd = fopen($file,"w"); 
  101.   fwrite($fd,"hi",2); 
  102.   sleep(1); 
  103.  
  104.  } 
  105.  for ($i=1;$i<=$instance->processNum;$i++){ 
  106.   posix_kill($instance->proc[$i]->pid,9); 
  107.  } 
  108.  fprintf(STDOUT,"master shutdown %d\n",$instance->processIdx); 
  109. } 
  110. function getProcess(&$instance) 
  111. { 
  112.  /** @var instance $instance */ 
  113.  return $instance->proc[$instance->processIdx]; 
  114. } 
  115. function worker(&$instance) 
  116. { 
  117.  /** @var process $process */ 
  118.  $process = getProcess($instance); 
  119.  while (1){ 
  120.   $file = $process->file; 
  121.   posix_mkfifo($file,0666); 
  122.   $fd = fopen($file,"r"); 
  123.   $content = fread($fd,10); 
  124.   fprintf(STDOUT,"worker#%d读取的内容:%s file=%d\n",posix_getpid(),$content,$file); 
  125.  } 
  126.  exit(0); 
  127. } 
  128.  
  129. $instance = new instance(); 
  130. processPool($instance,5); 

效果

PHP进程池 PHP轮询调度

Tags: PHP进程池 PHP轮询调度

分享到: