介紹看這裏 swoole的process
你們能夠先看看本身的swoole版本,在命令行裏面敲php
php --ri swoolehtml
更多的php命令行使用,你們學習 php命令行參數
ok 咱們直奔主題
怎麼用數組
很少說,直接上代碼緩存
<?php $worker_num =2;//建立的進程數 for($i=0;$i<$worker_num ; $i++){ $process = new swoole_process('callback_function_we_write'); $pid = $process->start(); echo PHP_EOL . $pid;// } function callback_function_we_write(swoole_process $worker){ echo PHP_EOL; var_dump($worker); echo PHP_EOL; }
運行結果以下swoole
5445 object(swoole_process)#1 (3) { ["pipe"]=> int(3) ["callback"]=> string(26) "callback_function_we_write" ["pid"]=> int(5445) } 5446 object(swoole_process)#2 (3) { ["pipe"]=> int(5) ["callback"]=> string(26) "callback_function_we_write" ["pid"]=> int(5446) }
能夠看到,咱們使用 new swoole_process 建立進程,這裏須要一個參數,也就是回調函數
當咱們使用 $process->start()執行後,返回這個進程的pid ,也就是 $pid.
此時子進程啓動,調用回調函數,並傳一個參數 也就是 swoole_process 類型的 $worker
我故意輸出了 $worker 看看裏面有什麼,結果有三個屬性函數
pipe 進程的管道id 這個等說道進程間通訊的時候再聊
pid 就是當前子進程的 pid 啦
callback 這個是咱們本身寫的回調函數名學習
到這裏,咱們就能夠用多進程玩耍了,
好比,咱們能夠測試多進程的運行速度測試
<?php echo PHP_EOL . time() ; $worker_num =3;//建立的進程數 for($i=0;$i<$worker_num ; $i++){ $process = new swoole_process('callback_function_we_write'); $pid = $process->start(); } function callback_function_we_write(swoole_process $worker){ for($i=0;$i<100000000;$i++){} echo PHP_EOL . time() ; }
我本機運行結果this
1435563435 // 開始時間
1435563438 //進程1 結束時間
1435563440 //進程2 結束時間
1435563440 //進程3 結束時間命令行
算三次 用了5s (其實通常是4s)
再玩一次
<?php echo PHP_EOL . time() ; for($i=0;$i<100000000;$i++){} for($i=0;$i<100000000;$i++){} for($i=0;$i<100000000;$i++){} echo PHP_EOL . time() ;
我本機運行結果
1435563704
1435563712
此次用了8s
作了這些,我想說明一個問題
並非說 單進程 要花8s 作完的活,咱們用3個進程就能將時間縮小三倍了
嘛,由於這是我之前的誤區
多進程還能夠這樣玩
<?php $funcMap=array('methodOne' , 'methodTwo' ,'methodThree' ); $worker_num =3;//建立的進程數 for($i=0;$i<$worker_num ; $i++){ $process = new swoole_process($funcMap[$i]); $pid = $process->start(); sleep(2); } while(1){ $ret = swoole_process::wait(); if ($ret){// $ret 是個數組 code是進程退出狀態碼, $pid = $ret['pid']; echo PHP_EOL."Worker Exit, PID=" . $pid . PHP_EOL; }else{ break; } } function methodOne(swoole_process $worker){// 第一個處理 echo $worker->callback .PHP_EOL; } function methodTwo(swoole_process $worker){// 第二個處理 echo $worker->callback .PHP_EOL; } function methodThree(swoole_process $worker){// 第三個處理 echo $worker->callback .PHP_EOL; }
我多加的sleep是爲了運行時看得更清楚,你也能夠去掉
這裏我使用了 swoole_process::wait() 詳解
目的是當子進程結束後,主進程可以知道。
咱們來想一個情景
過節了,媽媽要作飯,一看廚房裏缺了 油,鹽,糖,味精,十三香。因而吩咐兒子去小賣部買點回來。廚房這邊也不能閒着,老媽要繼續洗菜,切菜。等到調料買回來了,菜也洗好,切好了,開始炒,這邊炒好了一個菜,就要馬上送到餐桌上。
這個情景裏面,顯然使用了多進程,而且各進程作的不是一樣的事情。當子進程都完成了,主進程開始繼續業務。
如今有了一個問題,就拿上面的情景來講,兒子去買調味料,若是發現鹽沒有了,或者錢不夠了怎麼辦,如何與媽媽聯繫呢? 這就是下面要說的 進程間的通訊
Process 的通訊方式有兩種
管道
swoole_process->write(string $data);
swoole_process->read(int $buffer_size=8192);消息隊列
swoole_process->useQueue();
swoole_process->push(string $data);
swoole_process->pop(int $maxsize = 8192);
咱們先說說管道
這裏咱們要再次的說起進程的建立 new swoole_process
你們請看這裏 進程的建立
第一個參數是回調函數,不說了
第二個參數含義等會我會結合例子來講
第三個參數是默認的 true,意思是建立管道,你們還記得回調函數裏我特地將$worker輸出看到的內容嗎?
object(swoole_process)#1 (3) { ["pipe"]=> int(3) ["callback"]=> string(26) "callback_function_we_write" ["pid"]=> int(5445) }
關鍵是這裏的 pipe 這個就是本進程的管道id
咱們能夠這樣理解
每次建立一個進程後,就會隨之建立一個管道,主進程想和哪個進程通訊,就向那個進程的管道寫入/讀取數據。
ok,咱們看看代碼
<?php $redirect_stdout = false;// 重定向輸出 ; 這個參數用途等會咱們看效果 $worker_num = 2;//進程數量 $workers = [];//存放進程用的 for($i = 0; $i < $worker_num; $i++){ $process = new swoole_process('workerFunc',$redirect_stdout ); $pid = $process->start(); $workers[$pid] = $process;//將每個進程的句柄存起來 } // 這裏是主進程哦。 foreach($workers as $pid => $process){// $process 是子進程的句柄 $process->write("hello worker[$pid]\n");//子進程句柄向本身管道里寫內容 $process->write($data); echo "From Worker: ".$process->read();//子進程句柄從本身的管道里面讀取信息 $process->read(); echo PHP_EOL.PHP_EOL; } function workerFunc(swoole_process $worker){//這裏是子進程哦 $recv = $worker->read(); echo PHP_EOL. "From Master: $recv\n"; //send data to master $worker->write("hello master , this pipe is ". $worker->pipe ."; this pid is ".$worker->pid."\n"); sleep(2); $worker->exit(0); }
貼上運行結果
From Master: hello worker[8205] From Worker: hello master , this pipe is 3; this pid is 8205 From Master: hello worker[8206] From Worker: hello master , this pipe is 5; this pid is 8206
喔,通信是這樣的。
首先 將全部的子進程的句柄都存到 主進程的一個數組裏,數組下標就是pid。
當主進程想和哪一個進程通信,就使用那個句柄向對應管道里面 寫/讀 數據,這樣就實現了進程間的通信。
接着,咱們稍微改一下,看看運行效果
$redirect_stdout = true;// 重定向輸出 注意 此次我改爲 true 了,其餘沒變 $worker_num = 2;//進程數量 $workers = [];//存放進程用的 for($i = 0; $i < $worker_num; $i++){ $process = new swoole_process('workerFunc',$redirect_stdout ); $pid = $process->start(); $workers[$pid] = $process;//將每個進程的句柄存起來 } // 這裏是主進程哦。 foreach($workers as $pid => $process){// $process 是子進程的句柄 $process->write("hello worker[$pid]\n");//子進程句柄向本身管道里寫內容 $process->write($data); echo "From Worker: ".$process->read();//子進程句柄從本身的管道里面讀取信息 $process->read(); echo PHP_EOL.PHP_EOL; } function workerFunc(swoole_process $worker){//這裏是子進程哦 $recv = $worker->read(); echo PHP_EOL. "From Master: $recv\n"; //send data to master $worker->write("hello master , this pipe is ". $worker->pipe ."; this pid is ".$worker->pid."\n"); sleep(2); $worker->exit(0); }
輸出結果
From Worker: From Master: hello worker[8007] From Worker: From Master: hello worker[8008]
誒,不同了有沒有。咱們再看看建立進程時第二個參數的說明
$redirect_stdin_stdout,重定向子進程的標準輸入和輸出。 啓用此選項後,在進程內echo將不是打印屏幕,而是寫入到管道。讀取鍵盤輸入將變爲從管道中讀取數據。 默認爲阻塞讀取。
我來講明一下,由於建立的時候指定了true,子進程中echo的內容就到了管道里面,而不是打印在屏幕上(這一點相似於php的ob緩存機制,你們想象一下)
前面說了,進程的通信是經過從管道里面讀/寫數據實現的,而 子進程 裏 echo 的內容被 重定向到管道里面了,因此,主進程從管道里讀到的內容,就是 子進程中 echo 的 內容。
也就形成了上面的 輸出結果。
我先來個連接 利用PHP操做Linux消息隊列完成進程間通訊
重點是這個文章裏面的兩個連接文章啊,你們等會看看
還有一個命令
ipcs -q 查看當前的消息隊列
這部分 下次討論