pcntl擴充套件學習筆記一(pcntl_fork與pcntl_wait,序列執行分析)

helloworldcoding發表於2019-02-16

對程式設計的理解,應該到深入到作業系統級別。程式控制,我一直都沒有接觸,感覺好高階,今天啃了一下pcntl擴充套件的最簡單的兩個函式,有點心得,記錄一下吧,歡迎拋磚。
新建程式碼檔案 pcntl_wait.php,如下:

    $i = 0;
    while($i < 2) {
        $pid = pcntl_fork();
        // 父程式和子程式都會執行以下程式碼
        if ($pid == -1) { // 建立子程式錯誤,返回-1
            die(`could not fork`);
        } else if ($pid) {
            // 父程式會得到子程式號,所以這裡是父程式執行的邏輯
            pcntl_wait($status); // 父程式必須等待一個子程式退出後,再建立下一個子程式。
        
            $cid = $pid; // 子程式的ID
            $pid = posix_getpid(); // pid 與mypid一樣,是當前程式Id
            $myid = getmypid();
            $ppid = posix_getppid(); // 程式的父級ID
            $time = microtime(true);
            echo "I am parent cid:$cid   myid:$myid pid:$pid ppid:$ppid i:$i $time 
";
        } else {
            // 子程式得到的$pid 為0,所以這裡是子程式的邏輯
            $cid = $pid;
            $pid = posix_getpid();
            $ppid = posix_getppid();
            $myid = getmypid();
            $time = microtime(true);
            echo "I am child cid:$cid   myid:$myid pid:$pid ppid:$ppid i:$i  $time 
";
            //exit;
            //sleep(2);
        }
        $i++;
    }

php -f pcntl_wait.php 執行結果如下:

I am child   cid:0      myid:6499 pid:6499 ppid:6498 i:0  1491394182.2065
I am child   cid:0      myid:6500 pid:6500 ppid:6499 i:1  1491394182.2077
I am parent  cid:6500   myid:6499 pid:6499 ppid:6498 i:1  1491394182.2143
I am parent  cid:6499   myid:6498 pid:6498 ppid:3471 i:0  1491394182.2211
I am child   cid:0      myid:6501 pid:6501 ppid:6498 i:1  1491394182.222
I am parent  cid:6501   myid:6498 pid:6498 ppid:3471 i:1  1491394182.2302

為何是如上執行過程?
參考了PHP手冊和網友blog以上程式碼能夠迴圈產生子程式,並且父程式會阻塞等待子程式退出,這樣就產生了一個問題,父程式必須等待一個子程式退出後,再建立另外一個
個人分析如下:

1.執行shell命令(該程式ID是3471),生成主程式PID為6498

開始迴圈i=0

  6498 此時的父程式
   |fork  
  6499 父程式(6498阻塞),該子程式(6499)執行 ,輸出:child cid:0 myid:6499 pid:6499 ppid:6498 i:0  1491394182.2065
       然後i++ i=1,再次迴圈

繼續迴圈i=1

  6499 此時的父程式
   |fork
  6500 父程式(6499阻塞),該子程式(6500)執行,輸出:child cid:0  myid:6500 pid:6500 ppid:6499 i:1  1491394182.2077
       然後i++ i=2,本次迴圈終止,回到其主程式6499
  6499 解除阻塞,
       此時i=1(因為阻塞時i=1),繼續執行  輸出:parent cid:6500  myid:6499 pid:6499 ppid:6498 i:1  1491394182.2143
       然後i++ i=2,本次迴圈終止,回到其主程式6498
  6498 解除阻塞,
       此時i=0(因為阻塞時i=0),繼續執行,輸出:parent cid:6499  myid:6498 pid:6498 ppid:3471 i:0  1491394182.2211
       然後i++ i=1,再次迴圈

繼續迴圈i=1

  6498 此時的父程式
   |fork
  6501 父程式(6498阻塞),該子程式(6501)執行,輸出:child cid:0  myid:6501 pid:6501 ppid:6498 i:1  1491394182.222
       然後i++ i=2,本次迴圈終止,回到其主程式6498
  6498 解除阻塞
       此時i=1(因為阻塞時為i=1),繼續執行,輸出:parent cid:6501 myid:6498 pid:6498 ppid:3471 i:1  1491394182.2302      
       然後i++ i=2,本次迴圈終止,回到其主程式3471,最後命令結束。
             

相關文章