PHP多进程系列笔记(二)

        多进程实例

  1. 支持设置最大子进程数;

  2. Master-Worker结构:Worker挂掉,Master进程会重新创建一个;

<?php 

$pids = []; //存储子进程pid
$MAX_PROCESS = 3;//最大进程数

$pid = pcntl_fork();
if($pid < 0){
    exit("fork fail\n");
}elseif($pid > 0){
        ////父进程退出,子进程不是进程组长,以便接下来顺利创建新会话
    exit(0);
}else{
    // 最重要的一步,创建一个新的会话,脱离原来的控制终端
    if (posix_setsid() == -1) {
        die("could not detach from terminal");
    }

    $id = getmypid();   
    echo time()." Master process, pid {$id}\n"; 

    // 修改当前进程的工作目录,由于子进程会继承父进程的工作目录,修改工作目录以释放对父进程工作目录的占用。
        chdir('/');
    
    
    /*
         * 通过上一步,我们创建了一个新的会话组长,进程组长,且脱离了终端,但是会话组长可以申请重新打开一个终端,为了避免
         * 这种情况,我们再次创建一个子进程,并退出当前进程,这样运行的进程就不再是会话组长。
         */
    for($i=0; $i<$MAX_PROCESS;$i++){
        start_worker_process();
    }

    //Master进程等待子进程退出,必须是死循环
    while(1){
        foreach($pids as $pid){
            if($pid){
                $res = pcntl_waitpid($pid, $status, WNOHANG);
                if ( $res == -1 || $res > 0 ){
                    echo time()." Worker process $pid exit, will start new... \n";
                    start_worker_process();
                    unset($pids[$pid]);
                }
            }
        }
    }
}

/**
 * 创建worker进程
 */
function start_worker_process(){
    global $pids;
    $pid = pcntl_fork();
    if($pid <0){
        exit("fork fail\n");
    }elseif($pid > 0){
        $pids[$pid] = $pid;
        // exit; //此处不可退出,否则Master进程就退出了
    }else{
        //实际代码
        $id = getmypid();   
        $rand = rand(1,3);
        echo time()." Worker process, pid {$id}. run $rand s\n"; 
        while(1){
            sleep($rand);
        }
    }
}


冷暖自知一抹茶ck
请先登录后发表评论
  • 最新评论
  • 总共0条评论