首頁 >後端開發 >php教程 >php多進程之殭屍行程問題的解決詳解

php多進程之殭屍行程問題的解決詳解

黄舟
黄舟原創
2017-10-16 09:11:451850瀏覽

這篇文章主要介紹了PHP多進程編程之殭屍進程問題的理解的相關資料,希望透過本文能幫助到大家,讓大家掌握這部分內容,需要的朋友可以參考下

#PHP多進程編程之殭屍進程問題的理解

使用pcntl_fork函數可以讓PHP實現多進程並發或非同步處理的效果:http://www.jb51.net/article/ 125789.htm

那麼問題就是我們產生的進程需要去控制,而不能置之不理。最基本的方式就是fork進程和殺死進程。

透過利用pcntl_fork函數,我們已經有了新的子進程,而子進程接下來完成我們需要處理的內容,那麼我們就暫且叫做service()吧,而且我們需要很多個service()進行處理,再次參照我們先前的需求,父進程需要一直循環讀取設定文件,等待文件改變。透過對pcntl_fork的方式,很容易我們就可以寫出如下程式碼:


$res = config();
//kill进程
for($i = 0; $i < $res[sum]; $i++) {
  $pid = pcntl_fork();
  if ($pid == 0) {
    service();
    return;
  }
}

程式碼中註解的地方我們需要在設定檔中發生改變的時候殺死進程,殺死進程的方式很簡單,可以使用kill指令直接殺死,例如(假設pid為123):


1 kill 123

但我們發現,使用這個殺死行程的方式並沒有真正的把行程殺死,這個子行程被殺後還佔用這個行程的資源,我們成為殭屍行程,殭屍行程是使用kill指令無法殺死的。想要解決這個問題,我們能做的只有兩種方式。

1. shutdown

2. 殺死該行程的父行程。

但是這兩種方法都不行,因為這個程式的目的是監控常駐在伺服器內,伺服器不能關閉,而且父進程也不能被幹掉。這時候我們看到了官方文件對於fork方法的解釋:


pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。

原來有種方式可以防止進程成為殭屍進程,但是,官網給出的程式碼是這樣子的:


$pid = pcntl_fork();
//父进程和子进程都会执行下面代码
if ($pid == -1) {
  //错误处理:创建子进程失败时返回-1.
   die(&#39;could not fork&#39;);
} else if ($pid) {
   //父进程会得到子进程号,所以这里是父进程执行的逻辑
   pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。
} else {
   //子进程得到的$pid为0, 所以这里是子进程执行的逻辑。
}

是什麼意思呢?就是父行程會等待子行程運行,等子行程運行結束之後,才會進行下一步,也會消除殭屍行程。但是這裡又和我們的需求不符合了,我們的子進程為一個死循環的程序,不斷的查找輸出,更本沒有結束的時候,並且我們需要的是異步處理而不是同步。但是這個方法可以用嗎?其實當然可以。

在pcntl_wait的文檔中是這麼解釋這個函數的:

wait函數刮起當前程序的執行直到一個子進程退出或接收到一個信號要求中斷當前程序或調用一個信號處理函數。 如果一個子程序在呼叫此函數時已經退出(俗稱殭屍進程),此函數立刻回傳。子進程使用的所有系統資源將 被釋放。關於wait在您系統上工作的詳細規格請查看您系統的wait(2)手冊。

我們發現,當這個函式發現子行程成為了殭屍行程就會釋放殭屍行程的資源-前提是這個殭屍行程為這個父行程的子行程。那我們就可以巧妙的利用這個方式讓這些殭屍進程釋放資源了,所以就有瞭如下代碼:


#
 posix_kill(123, 9);
 pcntl_wait($status);

這樣我們先使用kill幹掉這個進程,這個進程就不會再運行了,但是這個進程成為了殭屍進程,佔用著資源,我們下一句就執行一次pcntl_wait()讓這些殭屍進程釋放資源,這樣,子進程才真正的被終止了,殭屍進程被消除了。

以上是php多進程之殭屍行程問題的解決詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn