php:多程式執行任務

bitsignal發表於2019-02-16

需求

對指定數量的多個任務併發執行,並控制程式數

程式&執行緒:

程式間相互獨立,不影響。

程式碼示例:

<?php

$task = 0; //任務id
$taskNum = 10; //任務總數
$processNumLimit = 2; //子程式總量限制

while(true){
   //產生分支
   $processid = pcntl_fork();

   //建立子程式失敗
   if( $processid == -1 ){
       echo "create process error!
";
       exit(1);
   }
   //主程式,獲得子程式pid
   elseif($processid){
       $task++; //下一個任務

       $currentProcessid = posix_getpid(); //當前程式的Id
       $parentProcessid = posix_getppid(); // 父級程式的ID
       $phpProcessid = getmypid(); //當前php程式的id
       echo "task:",$task,"	processid:",$processid,"	currentProcessid:",$currentProcessid,"	parentProcessid:",$parentProcessid,"	phpProcessid:",$phpProcessid,"
";

       //控制程式數
       if($task >= $processNumLimit) {
           echo "wait chl start!
";
           $exitid = pcntl_wait($status); //等待退出
           echo "wait chl end!extid:",$exitid,"	status:",$status,"
";
       }
       
       //任務總量控制
       if($task >= $taskNum) {
           echo "taskNum enough!
";
           break;
       }
   }
   //processid=0為新建立的程式
   else{
       //模擬不同任務的不同執行時長
       $sleep = rand(1, 5);

       $currentProcessid = posix_getpid(); //當前程式的Id
       $parentProcessid = posix_getppid(); // 父級程式的ID
       $phpProcessid = getmypid(); //當前php程式的id
       echo "task:",$task,"	processid:",$processid,"	currentProcessid:",$currentProcessid,"	parentProcessid:",$parentProcessid,"	phpProcessid:",$phpProcessid,"	sleep:",$sleep,"	begin!
";

       sleep($sleep);

       echo "task:",$task,"	processid:",$processid,"	currentProcessid:",$currentProcessid,"	parentProcessid:",$parentProcessid,"	phpProcessid:",$phpProcessid,"	sleep:",$sleep,"	end!
";
       
       exit(0); //子程式執行完後退出,防止進入迴圈建立子程式
   }
}

執行的結果:

task:1    processid:32225    currentProcessid:32224    parentProcessid:15053    phpProcessid:32224
task:0    processid:0    currentProcessid:32225    parentProcessid:32224    phpProcessid:32225    sleep:5    begin!
task:2    processid:32226    currentProcessid:32224    parentProcessid:15053    phpProcessid:32224
wait chl start!
task:1    processid:0    currentProcessid:32226    parentProcessid:32224    phpProcessid:32226    sleep:2    begin!
task:1    processid:0    currentProcessid:32226    parentProcessid:32224    phpProcessid:32226    sleep:2    end!
wait chl end!extid:32226    status:0
task:3    processid:32228    currentProcessid:32224    parentProcessid:15053    phpProcessid:32224
wait chl start!
task:2    processid:0    currentProcessid:32228    parentProcessid:32224    phpProcessid:32228    sleep:1    begin!
task:2    processid:0    currentProcessid:32228    parentProcessid:32224    phpProcessid:32228    sleep:1    end!
wait chl end!extid:32228    status:0
task:4    processid:32229    currentProcessid:32224    parentProcessid:15053    phpProcessid:32224
wait chl start!
task:3    processid:0    currentProcessid:32229    parentProcessid:32224    phpProcessid:32229    sleep:2    begin!
task:0    processid:0    currentProcessid:32225    parentProcessid:32224    phpProcessid:32225    sleep:5    end!
wait chl end!extid:32225    status:0
task:5    processid:32270    currentProcessid:32224    parentProcessid:15053    phpProcessid:32224
wait chl start!
task:4    processid:0    currentProcessid:32270    parentProcessid:32224    phpProcessid:32270    sleep:1    begin!
task:3    processid:0    currentProcessid:32229    parentProcessid:32224    phpProcessid:32229    sleep:2    end!
wait chl end!extid:32229    status:0
task:6    processid:32271    currentProcessid:32224    parentProcessid:15053    phpProcessid:32224
wait chl start!
task:5    processid:0    currentProcessid:32271    parentProcessid:32224    phpProcessid:32271    sleep:4    begin!
task:4    processid:0    currentProcessid:32270    parentProcessid:32224    phpProcessid:32270    sleep:1    end!
wait chl end!extid:32270    status:0
task:7    processid:32273    currentProcessid:32224    parentProcessid:15053    phpProcessid:32224
wait chl start!
task:6    processid:0    currentProcessid:32273    parentProcessid:32224    phpProcessid:32273    sleep:1    begin!
task:6    processid:0    currentProcessid:32273    parentProcessid:32224    phpProcessid:32273    sleep:1    end!
wait chl end!extid:32273    status:0
task:8    processid:32274    currentProcessid:32224    parentProcessid:15053    phpProcessid:32224
wait chl start!
task:7    processid:0    currentProcessid:32274    parentProcessid:32224    phpProcessid:32274    sleep:2    begin!
task:5    processid:0    currentProcessid:32271    parentProcessid:32224    phpProcessid:32271    sleep:4    end!
task:7    processid:0    currentProcessid:32274    parentProcessid:32224    phpProcessid:32274    sleep:2    end!
wait chl end!extid:32274    status:0
task:9    processid:32277    currentProcessid:32224    parentProcessid:15053    phpProcessid:32224
wait chl start!
wait chl end!extid:32271    status:0
task:8    processid:0    currentProcessid:32277    parentProcessid:32224    phpProcessid:32277    sleep:2    begin!
task:10    processid:32278    currentProcessid:32224    parentProcessid:15053    phpProcessid:32224
wait chl start!
task:9    processid:0    currentProcessid:32278    parentProcessid:32224    phpProcessid:32278    sleep:2    begin!
task:8    processid:0    currentProcessid:32277    parentProcessid:32224    phpProcessid:32277    sleep:2    end!
task:9    processid:0    currentProcessid:32278    parentProcessid:32224    phpProcessid:32278    sleep:2    end!
wait chl end!extid:32277    status:0
taskNum enough

執行分析:

  1. 在pcntl_fork出建立子程式後,子程式執行功能程式碼,父程式繼續遞增任務id,建立下一個任務程式;
  2. 通過pcntl_wait等待有子程式執行完畢退出後,再新建立程式,實現程式總數的控制;
  3. 在主程式完成建立後,通過break退出迴圈。此時可能有子程式繼續執行。

相關函式:

pcntl_fork

在當前程式當前位置產生分支(子程式)。成功時,在父程式執行執行緒內返回產生的子程式的PID,在子程式執行執行緒內返回0。失敗時,在 父程式上下文返回-1,不會建立子程式,並且會引發一個PHP錯誤。

pcntl_wait

等待或返回fork的子程式狀態。wait函式颳起當前程式的執行直到一個子程式退出或接收到一個訊號要求中斷當前程式或呼叫一個訊號處理函式。 如果一個子程式在呼叫此函式時已經退出(俗稱殭屍程式),此函式立刻返回。子程式使用的所有系統資源將 被釋放。

其他:

1.殭屍程式及孤兒程式的問題

部分殭屍程式被pcntl_wait獲取狀態並釋放資源,未接管的程式在主程式退出後成為孤兒程式。孤兒程式被init程式收養,完成wait的狀態獲取和資源釋放。

相關文章