pcntl_fork安裝以及實現PHP多進程


PHP有個pcntl_fork的函數可以實現多進程,但要加載pcntl拓展,而且只有在linux下才能編譯這個拓展,有時間在ubuntu下玩了下。

    1.首先在ubuntu下編譯pcntl.so,我的ubuntu下找不到pcntl的包,於是

創建一個文件夾下載了整個PHP包,在里面找到了pcntl包運行如下命令

# mkdir php
# cd php
# apt-get source php5
# cd php5-(WHATEVER_RELEASE)/ext/pcntl
# phpize
# ./configure (注一)
# make
# make install 

phpize 命令是用來准備 PHP 外掛模塊的編譯環境的。 

 

成功的安裝將建立 extname.so 並放置於 PHP 的外掛模塊目錄中 (預設存放於 /usr/lib/php/modules/ 內) 。
需要調整 php.ini,加入 extension=extname.so 這一行之后才能使用此外掛模塊。 

 

    2,開始實驗pcntl_fork

01 <?php
02 //while(1)//循環采用3個進程
03 //{
04 //declare(ticks=1);
05 $bWaitFlag = FALSE; // 是否等待進程結束
06 //$bWaitFlag = TRUE; // 是否等待進程結束
07 $intNum = 3; // 進程總數
08 $pids = array(); // 進程PID數組
09 for($i = 0; $i <$intNum; $i++)
10 {$pids[$i] = pcntl_fork();// 產生子進程,而且從當前行之下開試運行代碼,而且不繼承父進程的數據信息
11 /*if($pids[$i])//父進程
12 {
13 //echo $pids[$i]."parent"."$i -> " . time(). "\n";
14 }
15 */
16 if($pids[$i] == -1)
17 {
18 echo "couldn't fork". "\n";
19 }
20 elseif(!$pids[$i])
21 {
22 sleep(1);
23 echo "\n"."第".$i."個進程 -> " . time(). "\n";
24 //$url=" http://xxx/comments.php?p=".$i;//抓取頁面的例子
25 //$content = file_get_contents($url);
26 //file_put_contents('message.txt',$content);
27 //echo "\n"."第".$i."個進程 -> " ."抓取頁面".$i."-> " . time()."\n";
28 exit(0);//子進程要exit否則會進行遞歸多進程,父進程不要exit否則終止多進程
29 }
30 if ($bWaitFlag)
31 {
32 pcntl_waitpid($pids[$i], $status, WUNTRACED);echo "wait $i -> " . time() ."\n";}}
33 //sleep(1);
34 //}
35 ?>

保存為fork.php 在命令行運行 php fork.php

phpfork.png

pcntl函數還有一些功能沒實驗,例如進程狀態,根據相應狀態進行一些處理,運用多進程可以增加處理數據的效

率。在網上看到的fork的解釋:

fork之后,操作系統會復制一個與父進程完全相同的子進程,雖說是父子關系,但是在操作系統看來,他們更像兄弟關系,這2個進程共享代碼空間,但 是數據空間是互相獨立的,子進程數據空間中的內容是父進程的完整拷貝,指令指針也完全相同,但只有一點不同,如果fork成功,子進程中fork的返回值 是0,父進程中fork的返回值是子進程的進程號,如果fork不成功,父進程會返回錯誤。
可以這樣想象,2個進程一直同時運行,而且步調一致,在fork之后,他們分別作不同的工作,也就是分岔了。這也是fork為什么叫fork的原因。
至於那一個最先運行,可能與操作系統有關,而且這個問題在實際應用中並不重要,如果需要父子進程協同,可以通過原語的辦法解決。

----------------------------------------------

fork前父進程的東西子進程可以繼承,而在fork后子進程沒有任何和父進程的繼承關系了。在子進程里創建的東西是子進程的,在父進程創建的東西是父進程的。可以完全看成兩個進程。

----------------------------------------------

在程序段里用了fork();之后程序出了分岔,派生出了兩個進程。具體哪個先運行就看該系統的調度算法了。
在這里,我們可以這么認為,在運行到”pid=fork();”時系統派生出一個跟主程序一模一樣的子進程。該進程的”pid=fork();”一句中 pid得到的就是子進程本身的pid;子進程結束后,父進程的”pid=fork();”中pid得到的就是父進程本身的pid。因此改程序有兩行輸出。

----------------------------------------------

fork()函數復制了當前進程的PCB,並向父進程返回了派生子進程的pid。而且根據上面”corand”兄的提示,父子進程並行,打印語句的 先后完全看系統的調度算法。打印的內容控制則靠pid變量來控制。因為我們知道fork()向父進程返回了派生子進程的pid,是個正整數;而派生子進程 的pid變量並沒有被改變。這一區別使得我們看到了他們的不同輸出。

----------------------------------------------

1,派生子進程的進程,即父進程,其pid不變;
2,對子進程來說,fork返回給它0,但它的pid絕對不會是0;之所以fork返回0給它,是因為它隨時可以調用getpid()來獲取自己的pid;
3,fork之后父子進程除非采用了同步手段,否則不能確定誰先運行,也不能確定誰先結束。認為子進程結束后父進程才從fork返回的,這是不對的,fork不是這樣的,vfork才這樣。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM