利用PHP寫Multi Process程式
別問我怎麼會搞到要用 PHP 來寫 multi-process 程式,偏偏最近的案子裡就是有這種需要,不然我也是千百萬個不願意這樣寫…既然資料已經查了一堆,就寫出來給大家看吧。
PS: 預設讀者已知什麼是 multi-process programming ,並且什麼是 pid 。
PS: 預設讀者已知什麼是 multi-process programming ,並且什麼是 pid 。
1.1 產生子程序
1.1.1 產生一個子程序
在PHP裡沒有支援多執行緒編程 (multi-threaded programming) ,因此需要寫類似的功能就必須採取多程序編程 (multi-process programming) 的方式。一般在 unix-like 的作業系統下,要寫多程序程式一定會用到fork。在 PHP 裡也不例外。若要在 PHP 中建一個子程序,要叫用 pcntl_fork()函式。以下是一個簡單的程式樣版:樣版
<?php $pid = pcntl_fork(); //在這裡開始產生程式的分岔 if ($pid == -1) { die('無法產生子程序'); } else if ($pid) { // 父程序會進入這裡 } else { // 子程序會進入這裡 } ?>
- 子程序的 $pid 會是 0
- 父程序會拿到子程序的 $pid 編號。
- pcntl_fork() 函數目前只能在 Unix-like 的作業系統下使用(精確的說是有 System V API 的作業系統), PHP 目前沒有實作 Windows 環境下的版本。
- 有關 PHP 裡多程序的其它資料都在 PHP 官方網站上可以找得到。
1.1.2 產生多個子程序
以下這程式會造出多個子程序,子程序造出後父程序會等子程序全都離開後才離開。範例
<?php $process_num = 5; print "老爸:我是老爸,我要生{$process_num}個小孩。\n"; $children = array(); for($i = 1;$i <= $process_num; $i++) { $pid = pcntl_fork(); if($pid == -1) { exit(1); } else if ($pid) { /*這是老爸專區*/ $children[] = $pid; //紀錄下每個孩子的編號 print "老爸:生了一個第{$i}個孩子,pid是{$pid}\n"; } else { /*這是小朋友區*/ break; //直接出迴圈 } } if($pid) { /* 老爸會在這裡休息 */ $status = null; /******************************************************** * 下面這行的存在意義是: * 就算是等所有孩子先行離開以後 * 父程序才開始等子程序 * 父程序仍然會知道子程序已離開 **********************************************************/ sleep(8); foreach($children as $pid) { //要等每個孩子都離開才離開 pcntl_waitpid($pid, $status); print "老爸:pid是{$pid}的那個孩子,回去時他告訴我他的狀況是{$status}\n"; } print '老爸也要走了'."\n"; } else { /*以下是小朋友遊樂區*/ print "我是第{$i}個小朋友,我要睡{$i}秒\n"; sleep($i); print "我是第{$i}個小朋友,要走了\n"; exit(0); } ?>
解說
- 在此程式用到了 pcntl_waitpid() ,其參數是子程序的 $pid ,程式執行到此函式時,父行程會等到指定的子程序結束以後才繼續動作。
執行結果
老爸:我是老爸,我要生5個小孩。 我是第1個小朋友,我要睡1秒 老爸:生了一個第1個孩子,pid是10487 我是第2個小朋友,我要睡2秒 老爸:生了一個第2個孩子,pid是10488 我是第3個小朋友,我要睡3秒 老爸:生了一個第3個孩子,pid是10489 我是第4個小朋友,我要睡4秒 老爸:生了一個第4個孩子,pid是10490 我是第5個小朋友,我要睡5秒 老爸:生了一個第5個孩子,pid是10491 我是第1個小朋友,要走了 我是第2個小朋友,要走了 我是第3個小朋友,要走了 我是第4個小朋友,要走了 我是第5個小朋友,要走了 老爸:pid是10487的那個孩子,回去時他告訴我他的狀況是0 老爸:pid是10488的那個孩子,回去時他告訴我他的狀況是0 老爸:pid是10489的那個孩子,回去時他告訴我他的狀況是0 老爸:pid是10490的那個孩子,回去時他告訴我他的狀況是0 老爸:pid是10491的那個孩子,回去時他告訴我他的狀況是0 老爸也要走了
6 則留言:
感謝您的分享 :)
舉例易懂且有趣
您好,想請教如果在子程式裡做運算,如何回傳到父程序,謝謝。
很棒的範例與解釋,十分感謝!
淺顯易懂 謝謝分享:)
這篇寫的真牛,其他的我都看不董,淺顯易懂科普文
十幾年前的文章,還有人看,真是感動...
張貼留言