本节讲解几个多进程实例。多进程实例Master-Worker结构下面的例子实现简单的多进程管理:支持设置最大子进程数Master-Worker结构:Worker挂了,Master进程会重新创建一个0){exit;//parentprocessexit}else{//从当前终端分离if(posix_setsid()==-1){die("无法从终端分离");}$id=getmypid();echotime()."主进程,pid{$id}\n";for($i=0;$i<$MAX_PROCESS;$i++){start_worker_process();}//主进程等待子进程退出,一定是死循环while(1){foreach($pidsas$pid){if($pid){$res=pcntl_waitpid($pid,$status,WNOHANG);if($res==-1||$res>0){echotime()."Workerprocess$pidexit,willstartnew...\n";start_worker_process();取消设置($pids[$pid]);}}}}}/***创建工作进程*/functionstart_worker_process(){global$pids;$pid=pcntl_fork();if($pid<0){exit("fork失败\n");}elseif($pid>0){$pids[$pid]=$pid;//出口;//这里不能退出,否则Master进程会退出}else{//实际代码$id=getmypid();$rand=rand(1,3);echotime()."工作进程,pid{$id}。运行$rands\n";while(1){睡眠($rand);}}}~~~反盗版声明:本文为原创文章,发表于公众号飞鸿影博客(fhyblog)和博客园,转载需征得作者同意~~~多进程Server下面我们用多进程实现一个tcp服务器,支持:多进程处理客户端连接子进程退出,Master进程会重新创建一个支持事件回调0){exit;//父进程退出}else{//从当前终端分离if(posix_setsid()==-1){die("无法从终端分离");}掩码(0);$id=getmypid();echotime()."主进程,pid{$id}\n";//创建tcp服务器$this->socket=stream_socket_server("tcp://0.0.0.0:9201",$errno,$errstr);if(!$this->socket)exit("启动服务器错误:$errstr---$errno");}}publicfunctionrun(){for($i=0;$istart_worker_process();}回声“哇itingclient...\n";//主进程等待子进程退出,一定是死循环while(1){foreach($this->pidsas$k=>$pid){if($pid){$res=pcntl_waitpid($pid,$status,WNOHANG);如果($res==-1||$res>0){echotime()."workerprocess$pidexit,willstartnew...\n";$this->start_worker_process();unset($this->pids[$k]);}}}sleep(1);//放弃1sCPU时间}}/***创建工作进程并接受客户端结束连接*/privatefunctionstart_worker_process(){$pid=pcntl_fork();if($pid<0){exit("forkfail\n");}elseif($pid>0){$this->pids[]=$pid;//exit;//这里不能退出,否则Master进程会退出}else{$this->acceptClient();}}privatefunctionacceptClient(){//子进程一直在等待客户端连接,无法退出while(1){$conn=stream_socket_accept($this->socket,-1);如果($this->onConnect)call_user_func($this->onConnect,$conn);//回调连接事件//开始循环读取Fetchmessage$recv='';//实际收到消息$buffer='';//缓冲消息while(1){$buffer=fread($conn,20);//没有收到正常消息if($buffer===false||$buffer===''){if($this->onClose)call_user_func($this->onClose,$conn);//回调断开事件break;//结束读取Message,等待下一个client连接}$pos=strpos($buffer,"\n");//消息终止符if($pos===false){$recv.=$buffer;}else{$recv.=trim(substr($buffer,0,$pos+1));如果($this->onMessage)call_user_func($this->onMessage,$conn,$recv);//回调收到消息事件//客户端强行关闭连接if($recv=="quit"){echo"clientcloseconn\n";fclose($conn);休息;}$recv='';//清除消息并准备下一次接收}}}}function__destruct(){@fclose($this->socket);}}$server=newTcpServer();$server->onConnect=function($conn){echo"onConnect--accepted".stream_socket_get_name($conn,true)。"\n";fwrite($conn,"connsuccess\n");};$server->onMessage=function($conn,$msg){echo"onMessage--".$味精。"\n";fwrite($conn,"received".$msg."\n");};$server->onClose=function($conn){echo"onClose--".stream_socket_get_name($conn,true)。"\n";fwrite($conn,"onClose"."\n");};$server->run();运行:$phpprocess_multi.server.php1528734803Master进程,pid9110waitingclient...此时server已经变成守护进程了新开一个终端,使用ps命令查看进程:$ps-ef|grepphpyjc91101000:33?00:00:00phpprocess_multi.server.phpyjc91119110000:33?00:00:00phpprocess_multi.server.phpyjc91129110000:33?00:00:00phpprocess_multi.server.phpyjc91139110000:33?00:00:00phpprocess_multi.server.phpyjc91348589000:35pts/100:00:00grepphp可以看到4个进程:1个主进程和3个子进程。使用kill命令结束子进程,主进程会重新启动一个新的子进程。然后我们使用telnet测试连接:$telnet127.0.0.19201Trying127.0.0.1...Connectedto127.0.0.1.Escapecharacteris'^]'.connsuccesshelloserver!receivedhelloserver!quitreceivedquitConnectionclosedbyforeignhost.欢迎关注公众号及时获取最新文章推送!推荐!您每月只需2.5即可拥有带SSD的VPS!