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 相关文章推荐
PHP的开合式多级菜单程序
Oct 09 PHP
一个php作的文本留言本的例子(一)
Oct 09 PHP
PHP 获取客户端真实IP地址多种方法小结
May 15 PHP
php 冒泡排序 交换排序法
May 10 PHP
PHP 时间日期操作实战
Aug 26 PHP
注册页面之前先验证用户名是否存在的php代码
Jul 14 PHP
PHP更新购物车数量(表单部分/PHP处理部分)
May 03 PHP
php中smarty实现多模版网站的方法
Jun 11 PHP
php阿拉伯数字转中文人民币大写
Dec 21 PHP
Zend Framework教程之MVC框架的Controller用法分析
Mar 07 PHP
thinkPHP中volist标签用法示例
Dec 06 PHP
laravel 时间格式转时间戳的例子
Oct 11 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
PHP简单实现“相关文章推荐”功能的方法
2014/07/19 PHP
Laravel框架下的Contracts契约详解
2020/03/17 PHP
javascript 函数调用的对象和方法
2010/07/01 Javascript
iframe的onload在Chrome/Opera中执行两次Bug的解决方法
2011/03/17 Javascript
基于jquery的button默认enter事件(回车事件)。
2011/05/18 Javascript
js对象内部访问this修饰的成员函数示例
2014/04/27 Javascript
js和jquery中循环的退出和继续下一个循环
2014/09/03 Javascript
Redis基本知识、安装、部署、配置笔记
2015/03/05 Javascript
JS实现将Asp.Net的DateTime Json类型转换为标准时间的方法
2016/08/02 Javascript
Bootstrap CSS布局之列表
2016/12/15 Javascript
利用PM2部署node.js项目的方法教程
2017/05/10 Javascript
基于Bootstrap模态对话框只加载一次 remote 数据的解决方法
2017/07/09 Javascript
用python删除java文件头上版权信息的方法
2014/07/31 Python
python2.7读取文件夹下所有文件名称及内容的方法
2018/02/24 Python
用Python将mysql数据导出成json的方法
2018/08/21 Python
Win10下python3.5和python2.7环境变量配置教程
2018/09/18 Python
Pytorch 多块GPU的使用详解
2019/12/31 Python
python opencv根据颜色进行目标检测的方法示例
2020/01/15 Python
Python+Kepler.gl实现时间轮播地图过程解析
2020/07/20 Python
曼联官方网上商店:Manchester United Direct
2017/07/28 全球购物
Origins加拿大官网:雅诗兰黛集团高端植物护肤品牌
2017/11/19 全球购物
地球上最先进的胡子和头发修剪器:Bevel
2018/01/23 全球购物
廉价连衣裙和婚纱礼服在线销售:Tbdress
2019/02/28 全球购物
管理学专业个人求职信范文
2013/09/21 职场文书
机械设计制造专业个人求职信
2013/09/25 职场文书
毕业生求职找工作的自我评价范文
2013/11/27 职场文书
银行领导证婚词
2014/01/11 职场文书
搞笑获奖感言
2014/01/30 职场文书
毕业生银行实习自我鉴定
2014/10/14 职场文书
2014年英语教研组工作总结
2014/12/06 职场文书
计划生育目标责任书
2015/05/09 职场文书
2019让人心动的商业计划书
2019/06/27 职场文书
Python爬虫实战之爬取京东商品数据并实实现数据可视化
2021/06/07 Python
详解Python中的进程和线程
2021/06/23 Python
Python编程源码报错解决方法总结经验分享
2021/10/05 Python
Android Studio实现带三角函数对数运算功能的高级计算器
2022/05/20 Java/Android