本文實例講述了PHP共享內存用法。分享給大家供大家參考,具體如下:
共享內存主要用於進程間通信
php中的共享內存有兩套擴展可以實現
1、shmop 編譯時需要開啟 --enable-shmop 參數
實例:
$shm_key = ftok(__FILE__, 't'); /** 開辟一塊共享內存 int $key , string $flags , int $mode , int $size $flags: a:訪問只讀內存段 c:創建一個新內存段,或者如果該內存段已存在,嘗試打開它進行讀寫 w:可讀寫的內存段 n:創建一個新內存段,如果該內存段已存在,則會失敗 $mode: 八進制格式 0655 $size: 開辟的數據大小 字節 */ $shm_id = shmop_open($shm_key, "c", 0644, 1024); /** * 寫入數據 數據必須是字符串格式 , 最後一個指偏移量 * 注意:偏移量必須在指定的范圍之內,否則寫入不了 * */ $size = shmop_write($shm_id, 'songjiankang', 0); echo "write into {$size}"; #讀取的范圍也必須在申請的內存范圍之內,否則失敗 $data = shmop_read($shm_id, 0, 100); var_dump($data); #刪除 只是做一個刪除標志位,同時不在允許新的進程進程讀取,當在沒有任何進程讀取時系統會自動刪除 shmop_delete($shm_id); #關閉該內存段 shmop_close($shm_id);
2、用 Semaphore 擴展中的 sem 類函數 (用起來更方便,類似 key-value 格式)
// Get the file token key $key = ftok(__DIR__, 'a'); // 創建一個共享內存 $shm_id = shm_attach($key, 1024, 777); // resource type if ($shm_id === false) { die('Unable to create the shared memory segment'); } #設置一個值 shm_put_var($shm_id, 111, 'value'); #刪除一個key //shm_remove_var($shm_id, 111); #獲取一個值 $value = shm_get_var($shm_id, 111); var_dump($value); #檢測一個key是否存在 // var_dump(shm_has_var($shm_id, 111)); #從系統中移除 shm_remove($shm_id); #關閉和共享內存的連接 shm_detach($shm_id);
注意:這兩種方式不通用的
一個用共享內存和信號量實現的消息隊列
/** * 使用共享內存和信號量實現 * * 支持多進程, 支持各種數據類型的存儲 * 注: 完成入隊或出隊操作,盡快使用unset(), 以釋放臨界區 * */ class ShmQueue { private $maxQSize = 0; // 隊列最大長度 private $front = 0; // 隊頭指針 private $rear = 0; // 隊尾指針 private $blockSize = 256; // 塊的大小(byte) private $memSize = 25600; // 最大共享內存(byte) private $shmId = 0; private $filePtr = './shmq.ptr'; private $semId = 0; public function __construct () { $shmkey = ftok(__FILE__, 't'); $this->shmId = shmop_open($shmkey, "c", 0644, $this->memSize); $this->maxQSize = $this->memSize / $this->blockSize; // 申請一個信號量 $this->semId = sem_get($shmkey, 1); sem_acquire($this->semId); // 申請進入臨界區 $this->init(); } private function init () { if (file_exists($this->filePtr)) { $contents = file_get_contents($this->filePtr); $data = explode('|', $contents); if (isset($data[0]) && isset($data[1])) { $this->front = (int) $data[0]; $this->rear = (int) $data[1]; } } } public function getLength () { return (($this->rear - $this->front + $this->memSize) % ($this->memSize)) / $this->blockSize; } public function enQueue ($value) { if ($this->ptrInc($this->rear) == $this->front) { // 隊滿 return false; } $data = $this->encode($value); shmop_write($this->shmId, $data, $this->rear); $this->rear = $this->ptrInc($this->rear); return true; } public function deQueue () { if ($this->front == $this->rear) { // 隊空 return false; } $value = shmop_read($this->shmId, $this->front, $this->blockSize - 1); $this->front = $this->ptrInc($this->front); return $this->decode($value); } private function ptrInc ($ptr) { return ($ptr + $this->blockSize) % ($this->memSize); } private function encode ($value) { $data = serialize($value) . "__eof"; echo ''; echo strlen($data); echo ''; echo $this->blockSize - 1; echo ''; if (strlen($data) > $this->blockSize - 1) { throw new Exception(strlen($data) . " is overload block size!"); } return $data; } private function decode ($value) { $data = explode("__eof", $value); return unserialize($data[0]); } public function __destruct () { $data = $this->front . '|' . $this->rear; file_put_contents($this->filePtr, $data); sem_release($this->semId); // 出臨界區, 釋放信號量 } } /* * // 進隊操作 $shmq = new ShmQueue(); $data = 'test data'; $shmq->enQueue($data); * unset($shmq); // 出隊操作 $shmq = new ShmQueue(); $data = $shmq->deQueue(); * unset($shmq); */
linux下 用 ipc命令查看 ,用 ipcrm 命令可以刪除
更多關於PHP相關內容感興趣的讀者可查看本站專題:《PHP基本語法入門教程》、《PHP錯誤與異常處理方法總結》、《php程序設計算法總結》及《php面向對象程序設計入門教程》
希望本文所述對大家PHP程序設計有所幫助。