子進程的創建
一般的子進程的寫法是:
<?php$pid = pcntl_fork();if($pid == -1){ //創建失敗 die('could not fork');}else{ if($pid){ //從這里開始寫的代碼是父進程的 exit("parent!"); } else{ //子進程代碼,為防止不停的啟用子進程造成系統資源被耗盡的情況,一般子進程代碼運行完成后,加入exit來確保子進程正常退出。 exit("child"); }}?>
上邊的代碼如果創建子進程成功的話,系統就有了2個進程,一個為父進程,一個為子進程,子進程的id號為$pid。在系統運行到$pid = pcntl_fork();時,在這個地方進行分支,父子進程各自開始運行各自的程序代碼。代碼的運行結果是parent 和child,很奇怪吧,為什么一個if和else互斥的代碼中,都輸出了結果?其實是像上邊所說的,代碼在pcntl_fork時,一個父進程運行parent,一個子進程運行了child。在代碼結果上就顯示了parent和child。至于誰先誰后的問題,這得要看系統資源的分配了。
如果需要起多個進程來處理數據,可以根據數據的數量,按照約定好的數量比如說1000條一個進程來起子進程。使用for循環就可以了。
#如果獲得的總數小于或等于0,等待60秒,并退出 if ($count <= 0) { sleep(60); exit; } #如果大于1000,計算需要起的進程數 if ($count > 1000) { $cycleSize = ceil($count/1000); } else { $cycleSize = 1; } for ($i=0; $i<$cycleSize; $i++) { $pid = pcntl_fork(); if($pid == -1) { break; } else { if($pid) { #父進程獲得子進程的pid,存入數組 $pidArr[] = $pid; } else { //開始發送,子進程執行完自己的任務后,退出。 exit; } } } while(count($pidArr) > 0) { $myId = pcntl_waitpid(-1, $status, WNOHANG); foreach($pidArr as $key => $pid) { if($myId == $pid) unset($pidArr[$key]); } }
然后使用crontab,來使此PHP程序每隔一段時間自動執行。
當然,示例代碼比較簡單,具體還需要考慮怎么防止多個子進程執行到同一條數據或者當前進程處理數據未完成時,crontab又開始執行PHP文件啟用新的進程等等。
PHP多進程實現方式
下面來系統地整理一下PHP多進程的實現方式:
1. 直接方式
pcntl_fork() 創建一個進程,在父進程返回值是子進程的pid,在子進程返回值是0,-1表示創建進程失敗。跟C非常相似。
測試腳本 test.php
<?php // example of multiple processes date_default_timezone_set( 'Asia/Chongqing'); echo "parent start, pid ", getmypid(), "/n" ; beep(); for ($i=0; $i<3; ++$i){ $pid = pcntl_fork(); if ($pid == -1){ die ("cannot fork" ); } else if ($pid > 0){ echo "parent continue /n"; for ($k=0; $k<2; ++$k){ beep(); } } else if ($pid == 0){ echo "child start, pid ", getmypid(), "/n" ; for ($j=0; $j<5; ++$j){ beep(); } exit ; } } // *** function beep(){ echo getmypid(), "/t" , date( 'Y-m-d H:i:s', time()), "/n" ; sleep(1); }?>
新聞熱點
疑難解答