Process
- pcntl没有提供进程间通信的功能
- pcntl不支持重定向标准输入和输出
- pcntl只提供了fork这样原始的接口,容易使用错误
-
-
- 支持重定向标准输入和输出,在子进程内
echo
不会打印屏幕,而是写入管道,读键盘输入可以重定向为管道读取数据 - 配合
Event
模块,创建的PHP
子进程可以异步的事件驱动模式 - 提供了
exec
接口,创建的进程可以执行其他程序,与原PHP
父进程之间可以方便的通信
- 子进程异常退出时,自动重启
- 主进程异常退出时,子进程会继续执行,完成所有任务后退出
(new class{
public $mpid=0;
public $works=[];
public $max_precess=1;
public $new_index=0;
public function __construct(){
try {
swoole_set_process_name(sprintf('php-ps:%s', 'master'));
$this->mpid = posix_getpid();
$this->run();
$this->processWait();
}catch (\Exception $e){
}
}
public function run(){
for ($i=0; $i < $this->max_precess; $i++) {
$this->CreateProcess();
}
}
public function CreateProcess($index=null){
$process = new swoole_process(function(swoole_process $worker)use($index){
if(is_null($index)){
$index=$this->new_index;
$this->new_index++;
}
swoole_set_process_name(sprintf('php-ps:%s',$index));
for ($j = 0; $j < 16000; $j++) {
$this->checkMpid($worker);
echo "msg: {$j}\n";
sleep(1);
}
}, false, false);
$pid=$process->start();
$this->works[$index]=$pid;
return $pid;
}
public function checkMpid(&$worker){
if(!swoole_process::kill($this->mpid,0)){
$worker->exit();
}
}
public function rebootProcess($ret){
$pid=$ret['pid'];
$index=array_search($pid, $this->works);
if($index!==false){
$index=intval($index);
$new_pid=$this->CreateProcess($index);
echo "rebootProcess: {$index}={$new_pid} Done\n";
return;
}
throw new \Exception('rebootProcess Error: no pid');
}
public function processWait(){
while(1) {
if(count($this->works)){
$ret = swoole_process::wait();
if ($ret) {
$this->rebootProcess($ret);
}
}else{
break;
}
}
}