PHP多进程之pcntl扩展的使用详解
安裝
1.編譯php源碼時(shí)加入
--enable-pcntl2.在現(xiàn)有的環(huán)境下新增加擴(kuò)展
cd php-version/ext/pcntl phpize ./configure && make && make install echo "extension=pcntl.so" >> /etc/php.ini3.Mac下用brew安裝 例如我本地是php7.1.5
brew install php71-pcntl使用
header('content-type:text/html;charset=utf-8' ); // 必須加載擴(kuò)展 if (!function_exists("pcntl_fork")) { die("pcntl extention is must !"); } pcntl_signal(SIGCHLD, SIG_IGN); //如果父進(jìn)程不關(guān)心子進(jìn)程什么時(shí)候結(jié)束,子進(jìn)程結(jié)束后,內(nèi)核會(huì)回收。 $pid_dir = __dir__."/pid_files"; for($i=0; $i<3; $i++){$pid = pcntl_fork(); //創(chuàng)建子進(jìn)程 if($pid == -1){//錯(cuò)誤處理:創(chuàng)建子進(jìn)程失敗時(shí)返回-1.var_dump("fork failed");}if(!$pid){//子進(jìn)程得到的$pid為0, 所以這里是子進(jìn)程執(zhí)行的邏輯。 //子進(jìn)程代碼$pid = posix_getpid();$ppid = posix_getppid();$r = rand(0,100); //隨機(jī)數(shù)touch("$pid_dir/fork_child_process_{$i}_{$ppid}_{$pid}_{$r}");exit;}else{//父進(jìn)程會(huì)得到子進(jìn)程號(hào),所以這里是父進(jìn)程執(zhí)行的邏輯 //如果不需要阻塞進(jìn)程,而又想得到子進(jìn)程的退出狀態(tài),則可以注釋掉pcntl_wait($status)語(yǔ)句,或?qū)懗?#xff1a; pcntl_wait($status,WNOHANG); //等待子進(jìn)程中斷,防止子進(jìn)程成為僵尸進(jìn)程。} } $pid = posix_getpid(); $ppid = posix_getppid(); $r = rand(0,100); //隨機(jī)數(shù) touch("$pid_dir/fork_process_pid_{$ppid}_{$pid}_$r");相關(guān)參數(shù)
pcntl_waitpid
等待或返回fork的子進(jìn)程狀態(tài)。
多進(jìn)程的主進(jìn)程創(chuàng)建了子進(jìn)程,那主進(jìn)程如何確認(rèn)子進(jìn)程的狀態(tài)呢。 假如主進(jìn)程需要根據(jù)子進(jìn)程的狀態(tài)做不同的處理呢, 這里的狀態(tài)包括子進(jìn)程被kill掉,或變成僵尸進(jìn)程等。 pcntl_waitpid就可以獲取子進(jìn)程的狀態(tài)碼, 通過(guò)這個(gè)狀態(tài)碼, 就可知道子進(jìn)程處于什么狀態(tài)
他的用法:
返回的值可以是-1,0或者 >0的值, 如果是-1, 表示子進(jìn)程出錯(cuò), 如果>0表示子進(jìn)程已經(jīng)退出且值是退出的子進(jìn)程pid,至于如何退出, 可以通過(guò)$status狀態(tài)碼反應(yīng)。 那什么時(shí)候返回0呢, 只有在option 參數(shù)為 WNOHANG且子進(jìn)程正在運(yùn)行時(shí)0, 也就是說(shuō)當(dāng)設(shè)置了options=WNOHANG時(shí), 如果子進(jìn)程還沒(méi)有退出, 此時(shí)pcntl_waitpid就會(huì)返回0
另外, 如果不設(shè)置這個(gè)參數(shù)為WNOHANG, pcntl_waitpid 就會(huì)阻塞運(yùn)行, 直到子進(jìn)程退出, 至于option的另外一個(gè)值WUNTRACED, 暫未理解, 不表
那么如何根據(jù)$status(狀態(tài)碼)判斷進(jìn)程是如何退出呢, 如下(參數(shù)都是$status)
pcntl_wifexited
這個(gè)函數(shù)可以根據(jù)$status 判斷進(jìn)程是否正常退出, 何為正常退出, 比如exit
pcntl_wexitstatus
這個(gè)函數(shù)僅在pcntl_wifexited 返回True(即正常退出)時(shí)有效, 且返回子進(jìn)程退出的返回狀態(tài)碼, 這個(gè)返回狀態(tài)碼可以通過(guò)exit($s)的參數(shù)($s必須為整數(shù)時(shí))定義
pcntl_wifsignaled
檢查子進(jìn)程狀態(tài)碼是否代表由于某個(gè)信號(hào)而中斷, 比如是不是我們給他發(fā)送了term, int 等信號(hào)了
pcntl_wexitstatus
假如是發(fā)送信號(hào)而導(dǎo)致子進(jìn)程中斷, 那么這個(gè)信號(hào)是什么信號(hào)呢, 這個(gè)函數(shù)就是獲取這個(gè)信號(hào)的
pcntl_wifstopped
僅當(dāng)option選項(xiàng)為WUNTRACED時(shí)有效, 未理解, 不表
pcntl_wtermsig
同上
綜合實(shí)例代碼:
$res = pcntl_waitpid($pid, $status, WNOHANG); //FileLog::log("pid is $pid; wait result is $res"); if($res == -1 || $res > 0){if(!pcntl_wifexited($status)){//進(jìn)程非正常退出FileLog::log("service stop unusally; pid is $pid");}else{//獲取進(jìn)程終端的退出狀態(tài)碼;$code = pcntl_wexitstatus($status);FileLog::log("service stop code: $code;pid is $pid ");}if(pcntl_wifsignaled($status)){//不是通過(guò)接受信號(hào)中斷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");} }上面的這個(gè)代碼就通過(guò)根據(jù)pcntl_waitpid的返回結(jié)果和狀態(tài)碼對(duì)子進(jìn)程因?yàn)椴煌蛑袛嘧隽瞬煌奶幚?/p>
來(lái)源:https://www.lvtao.net/dev/php-pcntl-process.html
總結(jié)
以上是生活随笔為你收集整理的PHP多进程之pcntl扩展的使用详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 玫瑰之约电动车H1怎么激活4档?
- 下一篇: 予希字取名寓意好吗 予希取名的寓意