搜尋
首頁後端開發PHP7PHP7之多進程初探

PHP7之多進程初探

Apr 04, 2019 pm 01:52 PM
php7多行程

準備

我們都知道PHP是單一進程執行的,PHP處理多並發主要是依賴伺服器或PHP-FPM的多進程及它們進程的複用,但PHP實現多進程也意義重大,尤其是在後台Cli模式下處理大量資料或運行後台DEMON守護程式時,多進程的優勢不用多說。

PHP的多執行緒也曾被提及,但進程內多執行緒資源共享和分配的問題難以解決。 PHP也有多執行緒想關的擴充 pthreads ,但據說不太穩定,且要求環境為執行緒安全,所用不多。

以前PHP群裡的一位大神曾指導說後台PHP想進階必然避不開多進程,正好公司裡的守護進程也應用了PHP的多進程,結合著穀哥的各種資料和手冊,總算理解了多進程,並自己寫了一個小demo(在linux系統上實現的),用此文總結一下,如有錯漏,謝謝提出。

要實現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) {
    throw new Exception('fork child process fail');
} elseif ($pid > 0) {
    cli_set_process_title("我是父 process,pid is : {$ppid}.");
    sleep(30);
} else {
    $cpid = posix_getpid();
    cli_set_process_title("我是 {$ppid} 子的 process,我的 process pid is : {$cpid}.");
    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 ){
  echo "我是父亲".PHP_EOL;
} else if( 0 == $pid ) {
  echo "我是儿子".PHP_EOL;
} else {
  echo "fork失败".PHP_EOL;
} 

結果:

www@iZ2zec3dge6rwz2uw4tveuZ:~/test$ php 123.php
我是父亲
我是儿子

第二段程式碼,用來說明子進程擁有父進程的資料副本,而並不是共享:

// 初始化一个 number变量 数值为1
$number = 1;
$pid = pcntl_fork();
if ($pid > 0) {
    $number += 1;
    echo "我是父亲,number+1 : { $number }" . PHP_EOL;
} else if (0 == $pid) {
    $number += 2;
    echo "我是儿子,number+2 : { $number }" . PHP_EOL;
} else {
    echo "fork失败" . PHP_EOL;
}

結果

www@iZ2zec3dge6rwz2uw4tveuZ:~/test$ php 1234.php
我是父亲,number+1 : { 2 }
我是儿子,number+2 : { 3 }

以上是PHP7之多進程初探的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:cnblogs。如有侵權,請聯絡admin@php.cn刪除

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器