PHP共享内存用法实例分析
程序员文章站
2023-11-27 23:53:46
本文实例讲述了php共享内存用法。分享给大家供大家参考,具体如下:
共享内存主要用于进程间通信
php中的共享内存有两套扩展可以实现
1、shmop 编译...
本文实例讲述了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程序设计有所帮助。
上一篇: C#自定义事件监听实现方法
下一篇: php判断邮箱地址是否存在的方法