PHP共享内存用法实例分析


Posted in PHP onFebruary 12, 2016

本文实例讲述了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 相关文章推荐
Mysql的常用命令
Oct 09 PHP
PHP新手上路(十三)
Oct 09 PHP
PHP 检查扩展库或函数是否可用的代码
Apr 06 PHP
让PHP支持断点续传的源码
May 16 PHP
Windows下XDebug 手工配置与使用说明
Jul 11 PHP
PHPwind整合最土系统用户同步登录实现方法
Dec 08 PHP
PHP及Zend Engine的线程安全模型分析
Nov 10 PHP
php中fgetcsv()函数用法实例
Nov 28 PHP
完美解决phpdoc导出文档中@package的warning及Error的错误
May 17 PHP
关于PHP中字符串与多进制转换函数的实例代码
Nov 03 PHP
thinkphp Apache配置重启Apache1 restart 出错解决办法
Feb 15 PHP
PHP实现微信支付(jsapi支付)流程步骤详解
Mar 15 PHP
PHP连接MSSQL方法汇总
Feb 05 #PHP
Symfony2开发之控制器用法实例分析
Feb 05 #PHP
Symfony2实现在doctrine中内置数据的方法
Feb 05 #PHP
PHP MYSQL实现登陆和模糊查询两大功能
Feb 05 #PHP
twig模板获取全局变量的方法
Feb 05 #PHP
twig里使用js变量的方法
Feb 05 #PHP
Symfony2安装第三方Bundles实例详解
Feb 04 #PHP
You might like
解析二进制流接口应用实例 pack、unpack、ord 函数使用方法
2013/06/18 PHP
PHP输出日历表代码实例
2015/03/27 PHP
PHP 错误处理机制
2015/07/06 PHP
php验证手机号码
2015/11/11 PHP
IE与Firefox下javascript getyear年份的兼容性写法
2007/12/20 Javascript
jquery 图片Silhouette Fadeins渐显效果
2010/02/07 Javascript
javascript闭包的高级使用方法实例
2013/07/04 Javascript
js随机生成网页背景颜色的方法
2015/02/26 Javascript
javascript移动开发中touch触摸事件详解
2016/03/18 Javascript
详解vue.js的事件处理器v-on:click
2017/06/27 Javascript
vue中七牛插件使用的实例代码
2017/07/28 Javascript
判断滚动条滑到底部触发事件(实例讲解)
2017/11/15 Javascript
react-router4 配合webpack require.ensure 实现异步加载的示例
2018/01/18 Javascript
关于layui的下拉搜索框异步加载数据的解决方法
2019/09/28 Javascript
jsonp格式前端发送和后台接受写法的代码详解
2019/11/07 Javascript
Vue页面刷新记住页面状态的实现
2019/12/27 Javascript
VueCli4项目配置反向代理proxy的方法步骤
2020/05/17 Javascript
[50:50]完美世界DOTA2联赛PWL S3 Galaxy Racer vs Phoenix 第一场 12.10
2020/12/13 DOTA
python33 urllib2使用方法细节讲解
2013/12/03 Python
Python映射拆分操作符用法实例
2015/05/19 Python
Python使用设计模式中的责任链模式与迭代器模式的示例
2016/03/02 Python
PyQt5每天必学之创建窗口居中效果
2018/04/19 Python
CSS3 渐变(Gradients)之CSS3 径向渐变
2016/07/08 HTML / CSS
用CSS3打造HTML5的Logo(实现代码)
2016/06/16 HTML / CSS
Theory美国官网:后现代都市风时装品牌
2018/05/09 全球购物
日期和时间问题
2015/01/04 面试题
Java servlet面试题
2012/03/04 面试题
税务专业毕业生自荐信
2013/11/10 职场文书
《维生素c的故事》教学反思
2014/02/18 职场文书
捐助倡议书范文
2014/04/15 职场文书
团日活动总结书
2014/05/08 职场文书
最美护士演讲稿
2014/08/27 职场文书
中学生社会实践教育活动总结
2015/05/06 职场文书
四年级作文之植物
2019/09/20 职场文书
Mybatis-plus配置分页插件返回统一结果集
2022/06/21 Java/Android
Pytorch中expand()的使用(扩展某个维度)
2022/07/15 Python