>  기사  >  백엔드 개발  >  PHP 다중 프로세스 처리 병렬 작업

PHP 다중 프로세스 처리 병렬 작업

小云云
小云云원래의
2018-03-28 14:20:542198검색

이 기사에서는 Linux 환경에서 동시 작업 처리를 위해 PHP를 사용하는 방법과 프로세스 간 데이터 동기화를 위해 파이프를 사용하는 방법을 예제를 통해 설명합니다. 메모처럼 비교적 간단하게 작성했습니다.

PHP 다중 프로세스

pcntl_XXX 함수 시리즈를 통해 다중 프로세스 기능을 사용해보세요. 참고: pcntl_XXX는 php CLI(명령줄) 환경에서만 실행할 수 있습니다. 웹 서버 환경에서는 예측할 수 없는 결과가 발생할 수 있으므로 주의해서 사용하세요!

PIPE

Pipeline은 약어 간의 통신 데이터를 전달하는 데 사용됩니다. 이해를 돕기 위해 파이프를 파일과 비교할 수 있습니다. 프로세스 A는 파이프 P에 데이터를 쓴 다음 프로세스 B는 파이프 P에서 데이터를 읽습니다. PHP에서 제공하는 파이프라인 작업 API는 기본적으로 파일 작업을 위한 API와 동일합니다. 파이프라인을 생성하기 위해 posix_mkfifo 함수를 사용한다는 점을 제외하면 읽기 및 쓰기 작업은 파일 작업 함수와 동일합니다. 물론 파일을 직접 사용하여 파이프를 시뮬레이션할 수 있지만 파이프의 기능을 사용할 수는 없습니다.

좀비 프로세스

자식 프로세스가 종료되면 상위 프로세스는 이를 기다리지 않고(wait 또는 waitpid를 호출하여) 하위 프로세스가 종료된 후에 모든 리소스가 해제되지 않습니다(낭비!). 좀비 프로세스라고 불리는데, 자식 프로세스가 종료될 때 관련 데이터를 저장합니다. 좀비 프로세스가 너무 많으면 시스템 리소스(예: 메모리)를 많이 차지하여 시스템 성능에 영향을 미칩니다.

Code

/** 
 * this is a demo for php fork and pipe usage. fork use 
 * to create child process and pipe is used to sychoroize 
 * the child process and its main process. 
 * @author bourneli 
 * @date: 2012-7-6 
 */  
   
define("PC", 10); // 进程个数  
define("TO", 4); // 超时  
define("TS", 4); // 事件跨度,用于模拟任务延时  
   
if (!function_exists('pcntl_fork')) {  
    die("pcntl_fork not existing");  
}  
   
// 创建管道  
$sPipePath = "my_pipe.".posix_getpid();  
if (!posix_mkfifo($sPipePath, 0666)) {  
    die("create pipe {$sPipePath} error");  
}  
   
// 模拟任务并发  
for ($i = 0; $i < PC; ++$i ) {  
    $nPID = pcntl_fork(); // 创建子进程  
    if ($nPID == 0) {  
        // 子进程过程  
        sleep(rand(1,TS)); // 模拟延时  
        $oW = fopen($sPipePath, &#39;w&#39;);  
        fwrite($oW, $i."\n"); // 当前任务处理完比,在管道中写入数据  
        fclose($oW);  
        exit(0); // 执行完后退出  
    }  
}  
   
// 父进程  
$oR = fopen($sPipePath, &#39;r&#39;);  
stream_set_blocking($oR, FALSE); // 将管道设置为非堵塞,用于适应超时机制  
$sData = &#39;&#39;; // 存放管道中的数据  
$nLine = 0;  
$nStart = time();  
while ($nLine < PC && (time() - $nStart) < TO) {  
    $sLine = fread($oR, 1024);  
    if (empty($sLine)) {  
        continue;     
    }     
       
    echo "current line: {$sLine}\n";  
    // 用于分析多少任务处理完毕,通过‘\n’标识  
    foreach(str_split($sLine) as $c) {  
        if ("\n" == $c) {  
            ++$nLine;  
        }  
    }  
    $sData .= $sLine;  
}  
echo "Final line count:$nLine\n";  
fclose($oR);  
unlink($sPipePath); // 删除管道,已经没有作用了  
   
// 等待子进程执行完毕,避免僵尸进程  
$n = 0;  
while ($n < PC) {  
    $nStatus = -1;  
    $nPID = pcntl_wait($nStatus, WNOHANG);  
    if ($nPID > 0) {  
        echo "{$nPID} exit\n";  
        ++$n;  
    }  
}  
   
// 验证结果,主要查看结果中是否每个任务都完成了  
$arr2 = array();  
foreach(explode("\n", $sData) as $i) {// trim all  
    if (is_numeric(trim($i))) {  
        array_push($arr2, $i);    
    }  
}  
$arr2 = array_unique($arr2);  
if ( count($arr2) == PC) {    
    echo &#39;ok&#39;;   
} else {  
    echo  "error count " . count($arr2) . "\n";  
    var_dump($arr2);  
}

관련 권장 사항:

PHP 다중 프로세스 프로그래밍 예제에 대한 자세한 설명

위 내용은 PHP 다중 프로세스 처리 병렬 작업의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.