php進行進程間通訊的方式有好幾種:管道(Pipe)及有名管道(named pipe)、訊號(Signal)、封包(Message)佇列(訊息佇列)、共享記憶體、訊號量(semaphore)、套接口(Socket)。
本文列舉一個來介紹,那就是透過有名管道的方式。
管道用於承載簡稱之間的通訊資料。為了方便理解,可以將管道比喻為文件,進程A將資料寫到管道P中,然後進程B從管道P中讀取資料。
php提供的管道操作API與操作文件的API基本上一樣,除了建立管道使用posix_mkfifo函數,讀寫等操作都與檔案操作函數相同。
當然,你可以直接使用檔案模擬管道,但是那樣無法使用管道的特性了。
透過管道通訊的大概思路是,首先創建一個管道,然後子進程向管道中寫入信息,父進程從管道中讀取信息,這樣就可以做到父子進程直接實現通信了。
<?php /** * author: NickBai * createTime: 2016/12/2 0002 上午 11:12 */ //创建管道 $pipePath = "/tmp/test.pipe"; if( !file_exists( $pipePath ) ){ if( !posix_mkfifo( $pipePath, 0666 ) ){ exit('make pipe false!' . PHP_EOL); } } //创建进程,子进程写管道,父进程读管道 $pid = pcntl_fork(); if( $pid == 0 ){ //子进程写管道 $file = fopen( $pipePath, 'w' ); fwrite( $file, 'hello world' ); sleep(1); exit(); }else{ //父进程读管道 $file = fopen( $pipePath, 'r' ); //stream_set_blocking( $file, False ); //设置成读取非阻塞 echo fread( $file, 20 ) . PHP_EOL; pcntl_wait($status); //回收子进程 }
注意:本程式碼只能在linux下運行,並且只能在php-cli模式下。
第7行:指定一個管道的路徑,這裡跟普通檔案沒什麼差別。
第9行:透過 posix_mkfifo 函數建立 管道 並且設定讀寫權限為 0666
第15行:透過 pcntl_fork函數建立子程序。注意從現在開始,程式將會被分成兩個流程來執行。 pcntl_fork 函數 很特殊,它呼叫一次擁有 多個回傳值。在父進程中:它回傳 子進程的ID 這個值是 大於0 的。在子進程中,它回傳0。當傳回 -1 時表示建立進程失敗。
第17行:兩個行程根據目前行程所獲得的$pid的值不同,而進入不同的分支。
第18~22行:子程序開啟管道,並向其中寫入hello world ,然後進入休眠,休眠結束之後,退出。
第25~29行:父行程開啟管道,並進行讀取,最後執行 29行的程式碼回收掉子程序。這裡面兩個地方是阻塞的,首先是預設讀的地方,要等待子程序發出exit指令之後,才能回傳資料。還有就是回收進程的 pcntl_wait方法。要等到進程退出。
以上是php進程通訊有幾種方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!