PHP的pcntl進程控制教程二(pcntl_wait)

pcntl_wait 簡介

# 來源官方

pcntl_wait — 等待或返回fork的子進程狀態

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

wait函數颳起當前進程的執行直到一個子進程退出或接收到一個信號要求中斷當前進程或調用一個信號處理函數。 若是一個子進程在調用此函數時已經退出(俗稱殭屍進程),此函數馬上返回。子進程使用的全部系統資源將 被釋放。關於wait在您系統上工做的詳細規範請查看您系統的wait(2)手冊。

Note:
這個函數等同於以-1做爲參數pid 的值而且沒有options參數來調用pcntl_waitpid() 函數。

參數
status
pcntl_wait()將會存儲狀態信息到status 參數上,這個經過status參數返回的狀態信息能夠用如下函數 pcntl_wifexited(), pcntl_wifstopped(), pcntl_wifsignaled(), pcntl_wexitstatus(), pcntl_wtermsig()以及 pcntl_wstopsig()獲取其具體的值。

options
若是您的操做系統(多數BSD類系統)容許使用wait3,您能夠提供可選的options 參數。若是這個參數沒有提供,wait將會被用做系統調用。若是wait3不可用,提供參數 options不會有任何效果。options的值能夠是0 或者如下兩個常量或兩個常量「或運算」結果(即兩個常量表明意義都有效)。

options可用值
WNOHANG    若是沒有子進程退出馬上返回。
WUNTRACED    子進程已經退出而且其狀態未報告時返回。
返回值
pcntl_wait()返回退出的子進程進程號,發生錯誤時返回-1,若是提供了 WNOHANG做爲option(wait3可用的系統)而且沒有可用子進程時返回0。

測試代碼

<?php
/**
 * Created by PhpStorm.
 * User: Object
 * Date: 2018/6/11
 * Time: 10:28
 */
if (strtolower(php_sapi_name()) != 'cli') {
    die("請在cli模式下運行");
}

$index = 0;
$loop = 1;
while ($index < $loop) {

    echo "當前進程:" . getmypid() . PHP_EOL;
    $pid = pcntl_fork(); //fork出子進程

    if ($pid == -1) { // 建立錯誤,返回-1

        die('進程fork失敗');

    } else if ($pid) { // $pid > 0, 若是fork成功,返回子進程id

        // 父進程邏輯

        pcntl_wait($status); // 父進程必須等待一個子進程退出後,再建立下一個子進程。

        $child_id = $pid; //子進程的ID
        $pid = posix_getpid(); //獲取當前進程Id
        $ppid = posix_getppid(); // 進程的父級ID
        $time = microtime(true);
        echo "我是父進程,fork的子進程id: {$child_id};當前進程id:{$pid};父進程id:{$ppid}; 當前index:{$index}; 當前時間:{$time}".PHP_EOL;

    } else { // $pid = 0

        // 子進程邏輯
        $cid = $pid;
        $pid = posix_getpid();
        $ppid = posix_getppid();
        $myid = getmypid();
        $time = microtime(true);
        echo "我是子進程,當前進程id:{$pid};父進程id:{$ppid}; 當前index:{$index}; 當前時間:{$time}".PHP_EOL;
        //exit;
        //sleep(2);
    }
    $index++;
}

loop = 1 執行結果

當前進程:16604

我是子進程,當前進程id:16605;父進程id:16604; 當前index:0; 當前時間:1528696774.1978

我是父進程,fork的子進程id: 16605;當前進程id:16604;父進程id:15128; 當前index:0; 當前時間:1528696774.2032

loop = 2 執行結果

當前進程:16613

我是子進程,當前進程id:16614;父進程id:16613; 當前index:0; 當前時間:1528696781.4751

當前進程:16614

我是子進程,當前進程id:16615;父進程id:16614; 當前index:1; 當前時間:1528696781.4756

我是父進程,fork的子進程id: 16615;當前進程id:16614;父進程id:16613; 當前index:1; 當前時間:1528696781.4802

我是父進程,fork的子進程id: 16614;當前進程id:16613;父進程id:15128; 當前index:0; 當前時間:1528696781.4858

當前進程:16613

我是子進程,當前進程id:16616;父進程id:16613; 當前index:1; 當前時間:1528696781.4863

我是父進程,fork的子進程id: 16616;當前進程id:16613;父進程id:15128; 當前index:1; 當前時間:1528696781.4913

loop = 3 執行結果

當前進程:16625

我是子進程,當前進程id:16626;父進程id:16625; 當前index:0; 當前時間:1528696787.3334

當前進程:16626

我是子進程,當前進程id:16627;父進程id:16626; 當前index:1; 當前時間:1528696787.3338

當前進程:16627

我是子進程,當前進程id:16628;父進程id:16627; 當前index:2; 當前時間:1528696787.3345

我是父進程,fork的子進程id: 16628;當前進程id:16627;父進程id:16626; 當前index:2; 當前時間:1528696787.3391

我是父進程,fork的子進程id: 16627;當前進程id:16626;父進程id:16625; 當前index:1; 當前時間:1528696787.3434

當前進程:16626

我是子進程,當前進程id:16629;父進程id:16626; 當前index:2; 當前時間:1528696787.3441

我是父進程,fork的子進程id: 16629;當前進程id:16626;父進程id:16625; 當前index:2; 當前時間:1528696787.3496

我是父進程,fork的子進程id: 16626;當前進程id:16625;父進程id:15128; 當前index:0; 當前時間:1528696787.3543

當前進程:16625

我是子進程,當前進程id:16630;父進程id:16625; 當前index:1; 當前時間:1528696787.3548

當前進程:16630

我是子進程,當前進程id:16631;父進程id:16630; 當前index:2; 當前時間:1528696787.3555

我是父進程,fork的子進程id: 16631;當前進程id:16630;父進程id:16625; 當前index:2; 當前時間:1528696787.3599

我是父進程,fork的子進程id: 16630;當前進程id:16625;父進程id:15128; 當前index:1; 當前時間:1528696787.3643

當前進程:16625

我是子進程,當前進程id:16632;父進程id:16625; 當前index:2; 當前時間:1528696787.3649

我是父進程,fork的子進程id: 16632;當前進程id:16625;父進程id:15128; 當前index:2; 當前時間:1528696787.3697

總結

1.從執行的屢次結果得知,程序從外到內建立fork。而後再從內最後一次fork開始退出 2.如一次fork以後,程序的父進程因pcntl_wait阻塞,而後等待本次fork的子進程退出,而後相應的子進程的父進程執行邏輯並退出 3.而後執行本子進程的父進程依次循環2的邏輯退出,最終結束總進程
相關文章
相關標籤/搜索