我們都知道php是單程序執行的,php處理多併發主要是依賴伺服器或php-fpm的多程序及它們程序的復用,但php實現多程序也意義重大,尤其是在後台cli模式下處理大量資料或執行後台demon守護程序時,多程序的優勢不用多說。
php的多執行緒也曾被人提及,但程序內多執行緒資源共享和分配的問題難以解決。php也有多執行緒想關的擴充套件 pthreads ,但據說不太穩定,且要求環境為執行緒安全,所用不多。
以前php群裡的一位大神曾指導說後台php想高階必然避不開多程序,正好公司裡的守護程序也應用了php的多程序,結合著谷哥的各種資料和手冊,總算理解了多程序。
要實現php的多程序,我們需要兩個擴充套件 pcntl 和 posix,安裝方法這裡不再贅述。
在php中我們使用pcntl_fork()來建立多程序(在*nix系統的c語言程式設計中,已有程序通過呼叫fork函式來產生新的程序)。fork出來新程序則成為子程序,原程序則成為父程序,子程序擁有父程序的副本。這裡要注意:
• 子程序與父程序共享程式正文段
• 子程序擁有父程序的資料空間和堆、棧的副本,注意是副本,不是共享
• 父程序和子程序將繼續執行fork之後的程式**
• fork之後,是父程序先執行還是子程序先執行無法確認,取決於系統排程(取決於信仰)
這裡說子程序擁有父程序資料空間以及堆、棧的副本,實際上,在大多數的實現中也並不是真正的完全副本。更多是採用了cow(copy on write)即寫時複製的技術來節約儲存空間。簡單來說,如果父程序和子程序都不修改這些 資料、堆、棧 的話,那麼父程序和子程序則是暫時共享同乙份 資料、堆、棧。只有當父程序或者子程序試圖對 資料、堆、棧 進行修改的時候,才會產生複製操作,這就叫做寫時複製。
在呼叫完pcntl_fork()後,該函式會返回兩個值。在父程序中返回子程序的程序id,在子程序內部本身返回數字0。由於多程序在apache或者fpm環境下無法正常執行,所以大家一定要在php cli環境下執行**。
建立子程序
建立php子程序是多程序的開始,我們需要pcntl_fork()函式;
fork函式詳解
pcntl_fork() — 在當前程序當前位置產生分支(子程序)。此函式建立了乙個新的子程序後,子程序會繼承父程序當前的上下文,和父程序一樣從pcntl_fork() 函式處繼續向下執行,只是獲取到的pcntl_fork() 的返回值不同,我們便能從判斷返回值來區分父程序和子程序,分配父程序和子程序去做不同的邏輯處理。
pcntl_fork() 函式成功執行時會在父程序返回子程序的程序id(pid),因為系統的初始程序init程序的pid為1,後來產生程序的pid都會大於此程序,所以我們可以通過判斷pcntl_fork()的返回值大於1來確實當前程序是父程序;而在子程序中,此函式的返回值會是固定值0,我們也可以通過判斷pcntl_fork()的返回值為0來確定子程序;而pcntl_fork()函式在執行失敗時,會在父程序返回-1,當然也不會有子程序產生。
fork程序例項
fork子程序
$ppid = posix_getpid();
$pid = pcntl_fork();
if ($pid == -1) elseif ($pid > 0) .");
sleep(30);
} else 子的 process,我的 process pid is : .");
sleep(30);
}
說明:
posix_getpid():返回當前程序 id
cli_set_process_title('程序名稱'):為當前程序取乙個響亮的名字。
執行這個例子,我們便能看到當前兩個php程序了。
www@iz2zec3dge6rwz2uw4tveuz:~/test$ ps aux|grep -v grep |grep 我
www 18026 0.5 1.2 204068 25772 pts/0 s+ 14:08 0:00 我是父 process,pid is : 18026.
www 18027 0.0 0.3 204068 6640 pts/0 s+ 14:08 0:00 我 18026 子的 process,我的 process pid is : 18027.
第一段**,在程式從pcntl_fork()後父程序和子程序將各自繼續往下執行**:
$pid = pcntl_fork();
if( $pid > 0 ) else if( 0 == $pid ) else
結果:
www@iz2zec3dge6rwz2uw4tveuz:~/test$ php 123.php
我是父親
我是兒子
第二段**,用來說明子程序擁有父程序的資料副本,而並不是共享:
// 初始化乙個 number變數 數值為1
$number = 1;
$pid = pcntl_fork();
if ($pid > 0) " . php_eol;
} else if (0 == $pid) " . php_eol;
} else
結果
www@iz2zec3dge6rwz2uw4tveuz:~/test$ php 1234.php
我是父親,number+1 :
我是兒子,number+2 :
php 7 安裝多程序擴充套件
將 phpize 變成系統命令,使用ln 方式,命令為 ln s usr local php7 bin phpize usr bin phpize 第二步 在 root php 7.0.18 ext pcntl 目錄下執行 phpize 命令,生成編譯檔案。第三步 執行 configure 控制命令...
php多程序實現
php多程序實現 php有一組程序控制函式 編譯時需要 enable pcntl與posix擴充套件 使得php能在nginx系統中實現跟c一樣的建立子程序 使用exec函式執行程式 處理訊號等功能。方便極了。下面是示例 php view plain copy print header conten...
PHP7 網路程式設計(一)多程序初探
我們都知道php是單程序執行的,php處理多併發主要是依賴伺服器或php fpm的多程序及它們程序的復用,但php實現多程序也意義重大,尤其是在後台cli模式下處理大量資料或執行後台demon守護程序時,多程序的優勢不用多說。php的多執行緒也曾被人提及,但程序內多執行緒資源共享和分配的問題難以解決...