pcntl中php實現多進程必須要安裝的擴充,現將擴充安裝步驟寫在下面。
一、兩種安裝方式
1、重新編譯PHP的後面configrue提示加上?enable-pcntl。
2、不重新編譯php,直接編譯安裝pcntl擴充。
# cd /usr/local/src/php-5.2.6/ext/pcntl# /usr/local/php/bin/phpize# ./configure ?with-php-config=/usr/local/php/bin/php-config# make && make install
然後將,pcntl.so 加到php.ini中就可以了,使用php -m查看模組命令可以查看已安裝的模組。
二、執行個體
for($x = 1;$x<= 2;$x++){ $pid[$x] = pcntl_fork(); if ($pid[$x] == -1) { die("could not fork"); } elseif ($pid[$x]) { echo "Parent: create ".$pid[$x]."n"; } else { echo "fork ".getmypid()." start:n"; for($i = 0;$i<10;$i++){ echo $x.": ".$i."n"; sleep(1); } exit; }}
本文執行個體講述了PHP的pcntl多進程用法。分享給大家供大家參考。具體分析如下:
PHP使用PCNTL系列的函數也能做到多進程處理一個事務。比如我需要從資料庫中擷取80w條的資料,再做一系列後續的處理,這個時候,用單進程?你可以等到明年今天了。所以應該使用pcntl函數了。
假設我想要啟動20個進程,將1-80w的資料分成20份來做,主進程等待所有子進程都結束了才退出:
$max = 800000;$workers = 20; $pids = array();for($i = 0; $i < $workers; $i++){ $pids[$i] = pcntl_fork(); switch ($pids[$i]) { case -1: echo "fork error : {$i} \r\n"; exit; case 0: $param = array( 'lastid' => $max / $workers * $i, 'maxid' => $max / $workers * ($i+1), ); $this->executeWorker($input, $output, $param); exit; default: break; }} foreach ($pids as $i => $pid) { if($pid) { pcntl_waitpid($pid, $status); }}
這裡當pcntl_fork出來以後,會返回一個pid值,這個pid在子進程中看是0,在父進程中看是子進程的pid(>0),如果pid為-1說明fork出錯了。
使用一個$pids數組就可以讓主進程等候所有進程完結之後再結束了
例子測試
pcntl的擴充的安裝就不說了,很簡單,這裡結合執行個體說一下pcntl_fork的運行方式
<?php echo $pid= pcntl_fork(); if ($pid == -1) { die('could not fork'); } else if (!$pid) { //這裡是子進程 echo '-'; exit(); }else{ //這裡是父進程 echo 'A'; echo 'B'; }
我用cli運行多次的結果是
$pid為0說明是子進程,因為pcntl_fork()的作用就是當程式運行到這裡,就試圖去建立一個子進程,如果建立成果,那麼返回當前進程的子進程id,0表示當前進程沒有子進程,那麼其進程本身不就是子進程了,而如果有進程id,表示其有子進程,那麼其不就是父進程。就好像是從這個位置其,下面的所有代碼被複製到了另一個進程中執行一樣,產生了一個子進程。但是從上面多次執行結果看,大部分情況下是先執行子進程的,這和我之前網上查的資料有些出入,而且這個順序也不是固定的。但是我們發現倒數第三條,是先執行父進程,後執行的子進程,這時候子進程是有一定風險的,雖然子進程不會死,因為他會過繼到1進程,但如果要等待子進程執行完可以這樣:
<?php echo $pid= pcntl_fork(); if ($pid == -1) { die('could not fork'); } else if (!$pid) { //這裡是子進程 echo '-'; exit(); }else{ //這裡是父進程 echo 'A'; pcntl_wait($status);//父進程執行到這裡等等子進程執行完再執行 echo 'B'; } 運行結果: 0-31843AB[root@client 60.test.com]# php index.php 0-31845AB[root@client 60.test.com]# php index.php 0-31847AB[root@client 60.test.com]# php index.php 0-31849AB[root@client 60.test.com]# php index.php 0-31851AB[root@client 60.test.com]# php index.php 0-31853AB[root@client 60.test.com]# php index.php 0-31855AB[root@client 60.test.com]# php index.php 31857A0-B[root@client 60.test.com]# php index.php 0-31859AB[root@client 60.test.com]# php index.php 0-31861AB[root@client 60.test.com]# php index.php 0-31863AB[root@client 60.test.com]# php index.php 0-31865AB[root@client 60.test.com]# php index.php 0-31867AB[root@client 60.test.com]# php index.php 0-31869AB[root@client 60.test.com]# php index.php 0-31871AB[root@client 60.test.com]# php index.php 0-31873AB[root@client 60.test.com]# php index.php 0-31875AB[root@client 60.test.com]# php index.php 0-31877AB[root@client 60.test.com]# php index.php 0-31879AB[root@client 60.test.com]# php index.php 0-31881AB[root@client 60.test.com]# php index.php 0-31883AB[root@client 60.test.com]# php index.php
就是我們想要的結果了,其他都沒有問題,因為都是先執行的子進程,而這條是先執行了父進程,走到輸出A就等子進程執行完才執行的下面的。所以這就是
ntl_wait($status)
的作用。
好了,基本就是這些了。至於進程間或線程間的通訊,可以利用類似共用記憶體變數等的來做。具體情況具體對待吧。