前言

進(jìn)程間通信是一個永遠(yuǎn)的話題,我的上一篇文章通過一個并發(fā)循環(huán)ID生成器的實(shí)現(xiàn)介紹了如何使用外部介質(zhì)來進(jìn)行進(jìn)程間通信:從并發(fā)處理談PHP進(jìn)程間通信(一)外部介質(zhì) 。介紹的幾種方法適用于各種語言,但是他們都依賴于一種外部介質(zhì),文化的讀寫有瓶頸,mysql 和 redis 會掛掉或連接超時,歸根結(jié)底總覺得在 HACK;

對于進(jìn)程間通信,每一個完備的語言都應(yīng)該有對應(yīng)的處理方式,而 PHP 對應(yīng)的則是一族對 UNIX SYSTEM V包裝的函數(shù),包括信號量(semaphore)、共享內(nèi)存(shared memory)和消息隊(duì)列(msg queue)的操作。

它的安裝和使用非常簡單,在編譯 PHP 時添加 --enable-sysvsem --enable-sysvshm --enable-sysvmsg 參數(shù)就可以,當(dāng)然 Windows 上無法使用。

今天我們?nèi)耘f使用上一篇文章的例子來介紹 PHP 內(nèi)部實(shí)現(xiàn)的進(jìn)程間通信,在了解它們的具體使用之前,先簡單介紹一下信號量、共享內(nèi)存、消息隊(duì)列的概念。


Unix System V IPC

信號量

信號量又稱為信號燈,它是用來協(xié)調(diào)不同進(jìn)程間的數(shù)據(jù)對象的,而最主要的應(yīng)用是共享內(nèi)存方式的進(jìn)程間通信。本質(zhì)上,信號量是一個計(jì)數(shù)器,它用來記錄對某個資源(如共享內(nèi)存)的存取狀況。

一般說來,為了獲得共享資源,進(jìn)程需要執(zhí)行下列操作:

  1. 獲取控制共享資源的信號量的值;

  2. 若值為正,進(jìn)程將信號量減1,進(jìn)程操作共享資源,進(jìn)入步驟4;

  3. 若值0,則拒絕進(jìn)程使用共享資源,進(jìn)程進(jìn)入睡眠狀態(tài),直至信號量值大于0后,進(jìn)程被喚醒,轉(zhuǎn)入步驟1;

  4. 當(dāng)進(jìn)程不再使用共享資源時,將信號量值加1。如果此時有進(jìn)程正在睡眠等待此信號量,則喚醒此進(jìn)程;

信號量的使用可以類比為:

一個房間必須用鑰匙才能開門,有N把鑰匙放在門口,拿到鑰匙開門進(jìn)入房間,出來時將鑰匙放回并告知等待的人去取鑰匙開門。 此例中,鑰匙的數(shù)量限制了同一時間內(nèi)在房間的最大人數(shù)。房間即共享資源,鑰匙是信號量,而想進(jìn)入房間的人則是多個進(jìn)程。

信號量有二值和多值之分,一般共享資源都不允許多