PHP多程式學習(三)__程式碼案例來了解父程式與子程式的執行順序

OldBoy~發表於2018-02-02

pcntl_fork建立子程式成功的話,系統就有了2個程式,一個為父程式,一個為子程式,父程式和子程式都繼續向下執行,子程式的id號為$pid(父程式會獲取子程式的$pid也就是$pid不為0,而子程式會獲取$pid為0)在系統執行到$pid = pcntl_fork();時,在這個地方進行分支,父子程式各自開始執行各自的程式程式碼(通過if else語句判斷$pid我們就可以在指定位置寫上不同的邏輯程式碼)。

程式碼的執行結果是parent 和child,很奇怪吧,為什麼一個if和else互斥的程式碼中,都輸出了結果?其實是像上邊所說的,程式碼在pcntl_fork時,一個父程式執行parent,一個子程式執行了child。在程式碼結果上就顯示了parent和child。至於誰先誰後的問題,這得要看系統資源的分配了。

案例①

<?php
$pid = pcntl_fork();
 
if($pid == -1) {
    //錯誤處理:建立子程式失敗時返回-1.
    die('fork error');
} else if ($pid) {
    //父程式會得到子程式號,所以這裡是父程式執行的邏輯
    echo "parent \n";
    //等待子程式中斷,防止子程式成為殭屍程式。
    pcntl_wait($status);
} else {
    //子程式得到的$pid為0, 所以這裡是子程式執行的邏輯。
    echo "child \n";
 
    exit;
}
# php fork.php       //結果
parent 
child 

上述程式碼會經過多次執行,分別輸出parent和child。貌似是優先執行父程式。那麼輸出的parent和child是否會有順序之分?是父程式會先執行?下面繼續測試。。。

案例②

<?php
$pid = pcntl_fork();
 
if($pid == -1) {
    die('fork error');
} else if ($pid) {
    sleep(3);
    echo "parent \n";
    pcntl_wait($status);
} else {
    echo "child \n";
 
    exit;
}
# php fork.php  //結果
child 
parent 

我們在父程式中通過sleep來延緩執行,看看效果。
結果是,很快輸出了child,等待了接近3秒後,才輸出parent。所以父程式和子程式的執行是相對獨立的,沒有先後之分。

那麼問題又來了?pcntl_wait是做什麼用的?
會掛起當前程式,直到子程式退出,如果子程式在呼叫此函式之前就已退出,此函式會立刻返回。子程式使用的資源將被釋放。

案例③

<?php
$pid = pcntl_fork();
 
if($pid == -1) {
    die('fork error');
} else if ($pid) {
    pcntl_wait ($status);
    echo "parent \n";
} else {
    sleep(3);
    echo "child \n";
 
    exit;
}
# php fork.php  //結果 
child 
parent 

上述程式碼,我們可以看到,父程式執行pcntl_wait時就已經掛起,直到等待3秒後輸出child,子程式退出後。父程式繼續執行,輸出parent。

案例④

<?php
define('FORK_NUMS', 3);
 
$pids = array();
 
for($i = 0; $i < FORK_NUMS; ++$i) {
    $pids[$i] = pcntl_fork();
    if($pids[$i] == -1) {
        die('fork error');
    } else if ($pids[$i]) {
        pcntl_waitpid($pids[$i], $status);
        echo "pernet \n";
    } else {
        sleep(3);
        echo "child id:" . getmypid() . " \n";
        exit;
    }
}
# php fork.php  //結果 
child id:57534 
pernet 
child id:57538 
pernet 
child id:57540 
pernet 

上述程式碼,我們建立3個子程式,父程式分別掛起等待子程式結束後,輸出parent。

案例⑤

<?php
define('FORK_NUMS', 3);
 
$pids = array();
 
for($i = 0; $i < FORK_NUMS; ++$i) {
    $pids[$i] = pcntl_fork();
    if($pids[$i] == -1) {
        die('fork error');
    } else if ($pids[$i]) {
 
    } else {
        sleep(3);
        echo "child id:" . getmypid() . " \n";
        exit;
    }
}
 
foreach($pids as $k => $v) {
    if($v) {
        pcntl_waitpid($v, $status);
        echo "parent \n";
    }
}
# php fork.php  //結果
child id:57579 
child id:57581 
child id:57580 
parent 
parent 
parent 

為什麼上述程式碼跟例4的輸出結果不一樣?
我們可以看到案例⑤的pcntl_waitpid函式放在了foreach中,foreach程式碼是在主程式中,也就是父程式的程式碼中。當執行foreach時,可能子程式已經全部執行完畢並退出。pcntl_waitpid會立刻返回,連續輸出三個parent。
在子程式中,需通過exit來退出,不然會產生遞迴多程式,父程式中不需要exit,不然會中斷多程式。

案例⑥

<?php
 
define('FORK_NUMS', 3);
 
$pids = array();
 
$fp = fopen('./test.log', 'wb');
$num = 1;
 
for($i = 0; $i < FORK_NUMS; ++$i) {
    $pids[$i] = pcntl_fork();
    if($pids[$i] == -1) {
        die('fork error');
    } else if ($pids[$i]) {
 
 
    } else {
        for($i = 0; $i < 5; ++$i) {
 
            flock($fp, LOCK_EX);
            fwrite($fp, getmypid() . ' : ' . date('Y-m-d H:i:s') . " : {$num} \r\n");
 
            flock($fp, LOCK_UN);
            echo getmypid(), ": success \r\n";
            ++$num;
        }
        exit;
    }
}
 
foreach($pids as $k => $v) {
    if($v) {
        pcntl_waitpid($v, $status);
    }
}
 
fclose($fp);
# php fork.php         //結果 
57641: success 
57641: success 
57641: success 
57641: success 
57641: success 
57642: success 
57642: success 
57642: success 
57642: success 
57642: success 
57643: success 
57643: success 
57643: success 
57643: success 
57643: success 
//test.log  日誌內容  
57641 : 2018-02-02 15:55:48 : 1 
57641 : 2018-02-02 15:55:48 : 2 
57641 : 2018-02-02 15:55:48 : 3 
57641 : 2018-02-02 15:55:48 : 4 
57641 : 2018-02-02 15:55:48 : 5 
57642 : 2018-02-02 15:55:48 : 1 
57642 : 2018-02-02 15:55:48 : 2 
57642 : 2018-02-02 15:55:48 : 3 
57642 : 2018-02-02 15:55:48 : 4 
57642 : 2018-02-02 15:55:48 : 5 
57643 : 2018-02-02 15:55:48 : 1 
57643 : 2018-02-02 15:55:48 : 2 
57643 : 2018-02-02 15:55:48 : 3 
57643 : 2018-02-02 15:55:48 : 4 
57643 : 2018-02-02 15:55:48 : 5 

我們可以看到三個子程式的pid,它們分別執行了5次,時間幾乎是在同時。但是$num的值並沒像我們期望的那樣從1-15進行遞增。子程式中的變數是各自獨立的,互不影響。子程式會自動複製父程式空間裡的變數。

 

 

參考原文https://www.cnblogs.com/jkko123/p/6351690.html

相關文章