PHP對共用記憶體,訊息佇列的操作

來源:互聯網
上載者:User
PHP中對共用記憶體,訊息佇列的操作

php作為指令碼程式,通常生命週期都很短,如在web應用中,一次請求就是php啟動並執行一個周期,請求結束則生命週期截止。所以php在處理需要共用的資源時,一般會將共用資料儲存在資料庫或dbm之類的檔案中,再者就是利用記憶體實現共用。你可以選擇已有的工具輔助你,像memcache;也可以自己編寫代碼訪問作業系統的共用記憶體段。

php中對共用記憶體段的操作有兩組函數:SystemVIPC和SharedMemory。其中SystemVIPC系列函數能夠更方便的操作資料,無需像SharedMemory那樣必須自己掌握讀寫時的位移量、長度等,也不用序列化/還原序列化來迴轉換(因為SharedMemory函數只支援字串格式的資料參數)。但是SystemVIPC系列不支援Windows,所以如果要在win環境下使用,只能選SharedMemory。

因為php預設不支援這些函數,所以需要重編譯php。如要使用:

SystemV訊號量,編譯時間加上–enable-sysvsem

SystemV共用記憶體,編譯時間加上–enable-sysvshm

SystemV訊息佇列,編譯時間加上–enable-sysvmsg

SharedMemory,編譯時間加上–enable-shmop

先寫個SharedMemory的例子: 


再寫個System V shm的例子:


可以看到,sysV對於每個資料都另外設立了對應的var_key,這樣在同一記憶體地區可以儲存多個資料,而不用像shmop中那樣再申請另外一個共用記憶體地區,還免除了序列化的幹擾(雖然資料最終還是以序列化的形式儲存,但不用開發人員去手動實現)。

例子雖然簡單,但也有一些需要注意的地方,不管是shm_attach還是shmop_open,所申請的記憶體的大小一定要滿足後面資料的體積,這個體積包括資料本身序列化後的長,還有php添加的少量header資訊。php官方文檔中有人提出了一種計算要申請的記憶體大小的公式,這個公式可以保證所申請的記憶體足夠儲存一個指定的資料。公式如下:


這個公式是否適用於所有情況,我不敢說,所以我想最好還是在程式中,將準備放入共用記憶體的資料結構設計好,盡量保證資料大小在某一範圍內。

還有就是為了防止共用記憶體被浪費,當資料無用時及時調用對應的remove方法釋放資源。

介紹完共用記憶體再順帶提一下訊息佇列Message Queue(也是在System V IPC函數組中),訊息佇列似乎可以視為另一種共用記憶體,只是資料存放區的方式有些不同。簡單來說,就是每個key對應一個隊列,每個隊列可以儲存多個資料,資料間按照先進先出的原則進行操作。php文檔中的例子很好的介紹了各函數的應用:

 0) {msg_receive($seg, $argv[2], $msgtype, 1024, $data, true, MSG_IPC_NOWAIT);var_dump($msgtype);var_dump($data);echo "";} else {echo "No Msg...";}break;case "stat" :print_r(msg_stat_queue($seg));break;case "remove" :msg_remove_queue($seg);break;}?>

訊息佇列中的資料同樣受到大小的約束,具體約束範圍可通過msg_stat_queue的msg_qbytes看到。這段代碼唯一有點小改動的地方就在接受訊息時,指定了MSG_IPC_NOWAIT,不然如果目標隊列沒有資料,預設會一直等待。

一般會用到共用記憶體或訊息佇列的情況,都會涉及到多線程/進程,或跨語言的資料傳遞。如果是php指令碼/進程間共用資料,那隻要小心點操作就沒什麼問題。如果要求跨語言,那很可能遇到千奇百怪的問題,呵呵,我還沒試過,但在網上看到別人發的苦水貼,以後有機會一定實驗一下。

在調試共用記憶體、訊號量、訊息佇列時,可以配合Linux系統命令觀察資料存放區情況及訊號量、訊息佇列資源分派情況,如ipcs,ipcrm命令。

利用PHP操作Linux訊息佇列完成處理序間通訊

當我們開發的系統需要使用多進程方式運行時,處理序間通訊便成了至關重要的環節。訊息佇列(messagequeue)是Linux系統處理序間通訊的一種方式。

關於Linux系統進程通訊的概念及實現可查看:http://www.ibm.com/developerworks/cn/linux/l-ipc/

關於Linux系統訊息佇列的概念及實現可查看:http://www.ibm.com/developerworks/cn/linux/l-ipc/part4/

PHP的sysvmsg模組是對Linux系統支援的SystemVIPC中的SystemV訊息佇列函數族的封裝。我們需要利用sysvmsg模組提供的函數來進處理序間通訊。先來看一段範例程式碼_1:


這段代碼的運行結果如下:

resource(4) of type (sysvmsg queue)Array(    [msg_perm.uid] => 1000     [msg_perm.gid] => 1000    [msg_perm.mode] => 438    [msg_stime] => 0    [msg_rtime] => 0    [msg_ctime] => 1279849495    [msg_qnum] => 0    [msg_qbytes] => 16384    [msg_lspid] => 0    [msg_lrpid] => 0)Array(     [msg_perm.uid] => 1000     [msg_perm.gid] => 1000     [msg_perm.mode] => 438    [msg_stime] => 1279849495    [msg_rtime] => 0    [msg_ctime] => 1279849495     [msg_qnum] => 1    [msg_qbytes] => 16384    [msg_lspid] => 2184    [msg_lrpid] => 0)Hello,World!

  可以看到已成功從訊息佇列中讀取“Hello,World!”字串

  下面列舉一下範例程式碼中的主要函數:

  ftok ( string $pathname , string $proj )

  手冊上給出的解釋是:Convert a pathname and a project identifier to a System V IPC key。這個函數返回的索引值唯一對應linux系統中一個訊息佇列。在獲得訊息佇列的引用之前都需要調用這個函數。

  msg_get_queue ( int $key [, int $perms ] )

  msg_get_queue()會根據傳入的索引值返回一個訊息佇列的引用。如果linux系統中沒有訊息佇列與索引值對應,msg_get_queue()將會建立一個新的訊息佇列。函數的第二個參數需要傳入一個int值,作為新建立的訊息佇列的許可權值,預設為0666。這個許可權值與linux命令chmod中使用的數值是同一個意思,因為在linux系統中一切皆是檔案。

  msg_send ( resource $queue , int $msgtype , mixed $message [, bool $serialize [, bool $blocking [, int &$errorcode ]]] )

  顧名思義,該函數用來向訊息佇列中寫資料。

  msg_stat_queue ( resource $queue )

  這個函數會返回訊息佇列的中繼資料。訊息佇列中繼資料中的資訊很完整,包括了訊息佇列中待讀取的訊息數、最後讀寫隊列的進程ID等。範例程式碼在第8行調用該函數返回的數組中隊列中待讀取的訊息數msg_qnum值為0。

  msg_receive ( resource $queue , int $desiredmsgtype , int &$msgtype , int $maxsize , mixed &$message [, bool$unserialize [, int $flags [, int &$errorcode ]]] )

  msg_receive用於讀取訊息佇列中的資料。

  msg_remove_queue ( resource $queue )

  msg_remove_queue用於銷毀一個隊列。

  範例程式碼_1隻是展示了PHP操作訊息佇列函數的應用。下面的代碼具體描述了處理序間通訊的情境


運行結果為:
No.0 child process was created, the pid is 5249
No.1 child process was created, the pid is 5250
No.2 child process was created, the pid is 5251
No.3 child process was created, the pid is 5252
No.4 child process was created, the pid is 5253
process.5251 is writing now
this is process.5251's data
process.5253 is writing now
process.5252 is writing now
process.5250 is writing now
this is process.5253's data
this is process.5252's data
this is process.5250's data
process.5249 is writing now
this is process.5249's data
這段程式每次的運行結果都會不同,這正說明了多進程的非同步性。從結果也能看出訊息佇列FIFO特性。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.