成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

php pcntl 實踐填坑

魏明 / 1089人閱讀

摘要:多進程的主進程創(chuàng)建了子進程,那主進程如何確認(rèn)子進程的狀態(tài)呢。假如主進程需要根據(jù)子進程的狀態(tài)做不同的處理呢,這里的狀態(tài)包括子進程被掉,或變成僵尸進程等。

PHP 可以通過pcntl 擴展實現(xiàn)多進程編程, 而網(wǎng)上關(guān)于如何通過pcntl 創(chuàng)建多進程的在這里就不表了, 我主要說說關(guān)于pcntl_fork的一個坑和相關(guān)的比較生僻的幾個函數(shù)的使用方式, 這也是通過挖坑和填坑得出的結(jié)論。
閑言碎語不要講, 直接開始

pcntl_fork

在實踐中, 我在使用php進行多進程實踐的模型大概如下, 期待的是每個子進程都能創(chuàng)建一個與之對應(yīng)文件, 最后父進程創(chuàng)建一個屬于父進程的文件,代碼如下(有坑):

$pid_dir = __dir__."/pid_files";
for($i=0; $i<3; $i++){
    $pid = pcntl_fork();
    if($pid == -1){
        var_dump("fork failed");
    }
    if(!$pid){
        //子進程代碼
        $pid = posix_getpid();
        $ppid = posix_getppid();
        $r = rand(0,100);  //隨機數(shù)
        touch("$pid_dir/fork_child_process_{$i}_{$ppid}_{$pid}_{$r}");
    }
} 
$pid = posix_getpid();
$ppid = posix_getppid();
$r = rand(0,100); //隨機數(shù)
touch("$pid_dir/fork_process_pid_{$ppid}_{$pid}_$r");

上面的代碼我通過循環(huán)創(chuàng)建3個子進程, 每個進程創(chuàng)建一個文件,完成后到最后, 父進程創(chuàng)建一個屬于他自己的文件,所以, 最后應(yīng)該會創(chuàng)建出4個文件, 但事實并非如此:

fork_child_process_0_62656_62658_39
fork_child_process_1_62656_62659_51
fork_child_process_1_62658_62660_22
fork_child_process_2_62656_62661_91
fork_child_process_2_62658_62662_22
fork_child_process_2_62659_62663_82
fork_child_process_2_62660_62664_59
fork_process_pid_62225_62656_48
fork_process_pid_62656_62658_22
fork_process_pid_62656_62659_82
fork_process_pid_62656_62661_65
fork_process_pid_62658_62660_59
fork_process_pid_62658_62662_59
fork_process_pid_62659_62663_61
fork_process_pid_62660_62664_10

為何會出現(xiàn)上面的結(jié)果, 這是因為在fork之后, 原有的進程會分裂為兩個進程, 一個主進程, 一個子進程, fork后面所有的代碼都是共享的, 雖然通過fork的返回值可以判斷是主進程還是子進程來執(zhí)行相應(yīng)的子進程或主進程邏輯,但之后子進程自己又走到了for循環(huán)的部分, 子進程自己有創(chuàng)建了子進程, 所以上面看到了多個child_process 文件, 至于為什么是7個,
來分析一下。

=====================華麗的分割線=============================

循環(huán)變量$i, 當(dāng)$i為0時, 會產(chǎn)生一個主進程a(不變)和一個子進程aa,這個子進程創(chuàng)建了一個子進程文件,即fork_child_process_0_62656_62658_39, 主進程a繼續(xù)循環(huán), 即$i=1, 又創(chuàng)建了一個子進程ab, 他創(chuàng)建了fork_child_process_1_62656_62659_51, 主進程a繼續(xù)循環(huán)$i=2, 又創(chuàng)建了一個子進程ac, 他創(chuàng)建了fork_child_process_2_62656_62661_91這里可以看到62656就是主進程a的pid.

至此, 主進程a的循環(huán)完畢, 在看看a創(chuàng)建的第一個子進程aa, aa在創(chuàng)建之后, 創(chuàng)建好了上面的子進程文件之后并不會什么也不做, 他也會繼續(xù)走for的循環(huán), 而且繼承了主進程a的循環(huán)變量, 也就是$i的值為0,所以aa進程下一次的循環(huán)的$i就是1, 然后aa繼續(xù)創(chuàng)建了子進程aaa,從而創(chuàng)建文件fork_child_process_1_62658_62660_22,aa繼續(xù),$i=2, 又創(chuàng)建了一個子進程aab, 這個子進程創(chuàng)建了文件fork_child_process_2_62658_62662_22, 這里可以看到aaaaab的ppid就是aa的pid 62658,
同理aaa,aab 也繼承了aa的$i值,這時$i的值為1, 當(dāng)繼續(xù)循環(huán)時, $i 就變成了2, 也就只能循環(huán)一次了,相應(yīng)aaa,aab 創(chuàng)建了子進程文件fork_child_process_2_62659_62663_82(aaaa),fork_child_process_2_62660_62664_59(aaba),而他們相應(yīng)的父進程就是aaa(62659)和aab(62660).

至此, for循環(huán)中的多進程邏輯完成了, 也就是為何產(chǎn)生了第一部分的7個文件

=====================華麗的分割線=============================

而至于為何第二部分是8個文件, 各位可以自己思考一下, 注意, 無論主進程還是子進程, 在for循環(huán)完畢之后會繼續(xù)往下走, 知道這一點就好理解了。

在實際的代碼中, 我就犯了這種錯誤。
那如何解決上面的問題呢, 只要在子進程執(zhí)行的最后exit就好啦,

fork_child_process_0_63219_63221_66
fork_child_process_1_63219_63222_88
fork_child_process_2_63219_63223_22
fork_process_pid_62225_63219_77

繼續(xù),那么在網(wǎng)上看到很多多進程編程中使用pcntl_waitpid, 并不了解他是做什么的,且相應(yīng)的例子很少, 我暫且來說說我的理解

pcntl_waitpid

等待或返回fork的子進程狀態(tài)。
多進程的主進程創(chuàng)建了子進程,那主進程如何確認(rèn)子進程的狀態(tài)呢。 假如主進程需要根據(jù)子進程的狀態(tài)做不同的處理呢, 這里的狀態(tài)包括子進程被kill掉,或變成僵尸進程等。 pcntl_waitpid就可以獲取子進程的狀態(tài)碼, 通過這個狀態(tài)碼, 就可知道子進程處于什么狀態(tài)
他的用法:

int pcntl_waitpid ( int $pid , int &$status [, int $options = 0 ] )

返回的值可以是-1,0或者 >0的值, 如果是-1, 表示子進程出錯, 如果>0表示子進程已經(jīng)退出且值是退出的子進程pid,至于如何退出, 可以通過$status狀態(tài)碼反應(yīng)。 那什么時候返回0呢, 只有在option 參數(shù)為 WNOHANG且子進程正在運行時0, 也就是說當(dāng)設(shè)置了options=WNOHANG時, 如果子進程還沒有退出, 此時pcntl_waitpid就會返回0
另外, 如果不設(shè)置這個參數(shù)為WNOHANG, pcntl_waitpid 就會阻塞運行, 直到子進程退出, 至于option的另外一個值WUNTRACED, 暫未理解, 不表

那么如何根據(jù)$status(狀態(tài)碼)判斷進程是如何退出呢, 如下(參數(shù)都是$status)

pcntl_wifexited

這個函數(shù)可以根據(jù)$status 判斷進程是否正常退出, 何為正常退出, 比如exit

pcntl_wexitstatus

這個函數(shù)僅在pcntl_wifexited 返回True(即正常退出)時有效, 且返回子進程退出的返回狀態(tài)碼, 這個返回狀態(tài)碼可以通過exit($s)的參數(shù)($s必須為整數(shù)時)定義

pcntl_wifsignaled

檢查子進程狀態(tài)碼是否代表由于某個信號而中斷, 比如是不是我們給他發(fā)送了term, int 等信號了

pcntl_wexitstatus

假如是發(fā)送信號而導(dǎo)致子進程中斷, 那么這個信號是什么信號呢, 這個函數(shù)就是獲取這個信號的

pcntl_wifstopped

僅當(dāng)option選項為WUNTRACED時有效, 未理解, 不表

pcntl_wtermsig

同上

綜合實例代碼:

$res = pcntl_waitpid($pid, $status, WNOHANG);
//FileLog::log("pid is $pid; wait result is $res");
if($res == -1 || $res > 0){
    if(!pcntl_wifexited($status)){
        //進程非正常退出
        FileLog::log("service stop unusally; pid is $pid");
    }else{
        //獲取進程終端的退出狀態(tài)碼;
        $code = pcntl_wexitstatus($status);
        FileLog::log("service stop code: $code;pid is $pid ");
    }

    if(pcntl_wifsignaled($status)){
        //不是通過接受信號中斷
        FileLog::log("service stop not by signal;pid is $pid ");
    }else{
        $signal = pcntl_wtermsig($status);
        FileLog::log("service stop by signal $signal;pid is $pid");
    }
}

上面的這個代碼就通過根據(jù)pcntl_waitpid的返回結(jié)果和狀態(tài)碼對子進程因為不同原因中斷做了不同的處理

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/21087.html

相關(guān)文章

  • PHP回顧之多進程編程

    摘要:多進程中與多進程相關(guān)的兩個重要拓展是和。函數(shù)執(zhí)行期間,主進程除了等待無法處理其他任務(wù),所以一般不認(rèn)為這是多進程編程?;厥兆舆M程有兩種方式,一種是主進程調(diào)用函數(shù)等待子進程結(jié)束另外一種是處理信號。 轉(zhuǎn)載請注明文章出處: https://tlanyan.me/php-review... PHP回顧系列目錄 PHP基礎(chǔ) web請求 cookie web響應(yīng) session 數(shù)據(jù)庫操作 加解...

    lifesimple 評論0 收藏0
  • PHPpcntl進程控制教程一(pcntl_fork)

    摘要:說明函數(shù)創(chuàng)建一個子進程,這個子進程僅進程號和父進程號與其父進程不同。返回值成功時,在父進程執(zhí)行線程內(nèi)返回產(chǎn)生的子進程的,在子進程執(zhí)行線程內(nèi)返回。失敗時,在父進程上下文返回,不會創(chuàng)建子進程,并且會引發(fā)一個錯誤。 pcntl 簡介 PHP的進程控制支持實現(xiàn)了Unix方式的進程創(chuàng)建, 程序執(zhí)行, 信號處理以及進程的中斷。 進程控制不能被應(yīng)用在Web服務(wù)器環(huán)境,當(dāng)其被用于Web服務(wù)環(huán)境時可能會...

    LeexMuller 評論0 收藏0
  • multi-process-pcntl 基于PCNTLPHP并發(fā)處理 封裝類

    摘要:職場多年下來,技術(shù)也算是逐漸地有些積累,但是更重要的是對自身有了更加合理的人生定位?;蛟S,人生的意義,就在于此處的感悟吧?;诘牟l(fā)處理封裝類。對語言底層擴展的的深度解讀和生產(chǎn)應(yīng)用。函數(shù)官網(wǎng)手冊中對的說明,更細化的需求可以研究深化。 個人聲明 作者:于立(wx/yulichenr) 敬告:聯(lián)系我,請注明來源和來意 本人開發(fā)有很多年了,但是很少整理分享,如今趁著清閑就為大家服務(wù)了,希...

    awokezhou 評論0 收藏0
  • PHP多進程初探 --- 信號

    摘要:第一次子進程正在休眠中,父進程依舊在循環(huán)中。第三次此時父進程已經(jīng)執(zhí)行了,將已經(jīng)退出的子進程回收,釋放了等資源。梳理一下流程,子進程向父進程發(fā)送信號是對人們來說是透明的,也就是說我們無須關(guān)心。 [原文地址:https://blog.ti-node.com/blog...] 上一篇尬聊了通篇的pcntl_wait()和pcntl_waitpid(),就是為了解決僵尸進程的問題,但最后看起來...

    Prasanta 評論0 收藏0

發(fā)表評論

0條評論

魏明

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<