what
init程式
普通使用者執行但有超級許可權的程式
孤兒程式
父程式在子程式處理完前退出, 子程式就會變成孤兒程式;並由init程式進行處理
殭屍程式
- 「z+」標記
- 父程式fork子程式後, 沒有呼叫wait來維護子程式,導致子程式無人管理
why
總是不斷fork, 不管維護。系統資源有限 -- 就會出現殭屍程式
how
相比孤兒程式,殭屍程式危害更大,畢竟孤兒還有init媽媽來撫養,殭屍就只能獨自遊蕩!
pcntl_wait
pcntl_waitpid
等待或返回fork的子程式狀態
相同
pcntl_wait($status, $option) == pcntl_waitpid(-1, $status, $option)
pcntl_waitpid($pid, $status, $option)
pid
<-1: 等待任意程式組ID等於引數pid給定值的絕對值的程式
-1: 等待任意子程式;與pcntl_wait函式行為一致
0: 等待任意與呼叫程式組ID相同的子程式
0: 等待程式號等於引數pid值的子程式
option
WNOHANG: 如果沒有子程式退出立刻返回
WUNTRACED: 子程式已經退出並且其狀態未報告時返回
孤兒程式
<?php
$pid = pcntl_fork();
switch($pid) {
case 0:
// 子程式
echo "I am son parent's pid=".posix_getppid()."\n";
for( $i = 1; $i <= 10; $i++ ){
sleep( 1 );
// posix_getppid()函式的作用就是獲取當前程式的父程式程式ID
echo "parent's pid =" posix_getppid().PHP_EOL;
}
break;
case -1:
// fork error
echo "I am err\n";
break;
default:
// 父程式
echo "I am parent pid=".posix_getpid()."\n";
sleep(2);
break;
}
// 第三秒後 由init程式收養
殭屍程式
<?php
$pid = pcntl_fork();
switch($pid) {
case 0:
// 子程式
cli_set_process_title("son process php");
sleep(5);
break;
case -1:
// fork error
break;
default:
// 父程式
cli_set_process_title("parent process php");
sleep(30);
break;
}
// 子程式執行後父程式未取管理導致
解決
<?php
switch($pid) {
case 0:
// 子程式
cli_set_process_title("son process php");
sleep(10);
break;
case -1:
// fork error
break;
default:
// 父程式
cli_set_process_title("parent process php");
$iid = pcntl_wait($status); // 等待子程式的狀態處理
// 監控子程式狀態處理後才能輸出
// 只要未觸發pcntl_wait,此後的邏輯一直不會處理
echo $iid."-----\n";
//sleep(60);
break;
}
===
// 增加pcntl_wait
// pcntl_wait($status); // 只要子程式不退出, 父程式就會阻塞再這個地方
更優解決
<?php
$pid = pcntl_fork();
switch($pid) {
case 0:
// 子程式
cli_set_process_title("son process php");
sleep(10);
break;
case -1:
// fork error
break;
default:
// 父程式
cli_set_process_title("parent process php");
pcntl_waitpid($pid, $status, WNOHANG); // 監控$pid, 如果沒有子程式退出立刻返回
echo "I am parent\n";
//sleep(60);
break;
}
===
// pcntl_wait改寫pcntl_waitpid
// pcntl_waitpid($pid, $status, WNOHANG);
// 如果再pcntl_waitpid後續增加sleep, 還是會殭屍程式
更更優解決
訊號