PHP 多程式之孤兒和殭屍簡單講解

taozywu發表於2019-07-15

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, 還是會殭屍程式

更更優解決

訊號

相關文章