1. 程式人生 > >php多進程編程實現與優化

php多進程編程實現與優化

exist RR 執行 erl php code trace HP void

PHP多進程API

創建子進程

@params void
@returns int
int pcntl_fork(void)
成功時,在父進程執行線程內返回產生的子進程PID,在子進程執行線程內返回0,失敗時,在父進程上下文返回-1,不會創建子進程,並且會引發一個php錯誤

獲取當前進程id

@params void
@returns int
int posix_getpid(void)
返回進程id,類型為整型

父進程等待子進程退出

@params $status
@params $option
@return bool
int pcntl_wait(int &$status[,int $options
=0]) 該函數等同於以-1作為參數pid的值並且沒有options參數來調用pcntl_waitpid()的函數

進程退出狀態

@params $status
@return bool
bool pcntl_wifexited(int $status)

進程退出碼

@params $status
@return int
int pcntl_wexitstatus(int $status)

簡單PHP多進程示例

function process_execute($input) {
        $pid = pcntl_fork(); //創建子進程
        if ($pid == 0) {//子進程
$pid = posix_getpid(); echo "* Process {$pid} was created, and Executed:\n\n"; eval($input); //解析命令 exit; } else {//主進程 $pid = pcntl_wait($status, WUNTRACED); //取得子進程結束狀態 if (pcntl_wifexited(
$status)) { echo "\n\n* Sub process: {$pid} exited with {$status}"; } }

通過調用php創建子進程接口完成一個子進程的創建,pcntl_fork返回值為0證明進入到子進程內,非0則進入到父進程內部,-1則父進程創建子進程失敗。

多個子進程初級版本示例

foreach ($clusterList as $key=>$value) {
            $pid = pcntl_fork();//創建子進程
            if($pid == 0) {//子進程
                //do something
            } else if($pid == -1) {
                //fork error occured
            } else {
                pcntl_wait($status);
            }

        }

該實現方式主要邏輯為循環創建一個子進程,並且父進程等待子進程完成退出後,再繼續創建下一個子進程
缺點:無法真正體現多進程,實際上時串行的創建子進程

多個子進程優化版本示例

foreach ($clusterList as $key=>$value) {
            $pid = pcntl_fork();//創建子進程
            if($pid == 0) {//子進程
                //do something
            } else if($pid == -1) {
                return false;
            }
        }
        for (;;) {
            $ret = pcntl_waitpid(-1,$status,WNOHANG);
            if ($ret == -1) {
                // error occured 
            } else if ($ret == 0) {
                //all child are existed
                break;
            } else {
                //check sub process exit status
                $extFlag = pcntl_wifexited($status);
                if(!$extFlag){
                    //exited unnormally
                }else {
                    $extCode = pcntl_wexitstatus($status);
                    //exited normally
                }
            }
        }

該邏輯通過for循環不斷獲取子進程的退出狀態,直到所有的子進程都退出,真正實現多進程處理。

php多進程編程實現與優化