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 相关文章推荐
15个小时----从修改程序到自己些程序
Oct 09 PHP
php 文章调用类代码
Aug 11 PHP
探讨如何在php168_cms中提取验证码
Jun 08 PHP
如何使用php输出时间格式
Aug 31 PHP
PHP使用range协议实现输出文件断点续传代码实例
Jul 04 PHP
destoon实现底部添加你是第几位访问者的方法
Jul 15 PHP
php中的ini配置原理详解
Oct 14 PHP
php的ZipArchive类用法实例
Oct 20 PHP
PHP GD库相关图像生成和处理函数小结
Sep 30 PHP
Laravel 微信小程序后端搭建步骤详解
Nov 26 PHP
php获取是星期几的的一些常用姿势
Dec 15 PHP
深入分析PHP设计模式
Jun 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
Avengerls vs Newbee BO3 第一场2.18
2021/03/10 DOTA
javascript css在IE和Firefox中区别分析
2009/02/18 Javascript
IE和FireFox(FF)中js和css的不同
2009/04/13 Javascript
JS下高效拼装字符串的几种方法比较与测试代码
2010/04/15 Javascript
javascript 获取页面的高度及滚动条的位置的代码
2010/05/06 Javascript
JQuery Study Notes 学习笔记(一)
2010/08/04 Javascript
修改jQuery Validation里默认的验证方法
2012/02/14 Javascript
JavaScript charCodeAt方法入门实例(用于取得指定位置字符的Unicode编码)
2014/10/17 Javascript
AngularJS 验证码60秒倒计时功能的实现
2017/06/05 Javascript
jQuery菜单实例(全选,反选,取消)
2017/08/28 jQuery
Array数组对象中的forEach、map、filter及reduce详析
2018/08/02 Javascript
使用kbone解决Vue项目同时支持小程序问题
2019/11/08 Javascript
Node.js设置定时任务之node-schedule模块的使用详解
2020/04/28 Javascript
jQuery 实现扁平式小清新导航
2020/07/07 jQuery
[01:06]DOTA2亚洲邀请赛专属珍藏-荧煌之礼
2017/03/24 DOTA
python实现系统状态监测和故障转移实例方法
2013/11/18 Python
详细介绍Python函数中的默认参数
2015/03/30 Python
python对html代码进行escape编码的方法
2015/05/04 Python
MySQL最常见的操作语句小结
2015/05/07 Python
Django跨域请求CSRF的方法示例
2018/11/11 Python
Python实现的字典排序操作示例【按键名key与键值value排序】
2018/12/21 Python
Python常用模块之requests模块用法分析
2019/05/15 Python
Python日志:自定义输出字段 json格式输出方式
2020/04/27 Python
哈工大自然语言处理工具箱之ltp在windows10下的安装使用教程
2020/05/07 Python
使用opencv识别图像红色区域,并输出红色区域中心点坐标
2020/06/02 Python
详解python os.path.exists判断文件或文件夹是否存在
2020/11/16 Python
详解css3自定义滚动条样式写法
2017/12/25 HTML / CSS
信访工作者先进事迹
2014/01/17 职场文书
宝宝满月酒主持词和仪式流程
2014/03/27 职场文书
食品采购员岗位职责
2014/04/14 职场文书
法院先进个人事迹材料
2014/05/04 职场文书
有关骆驼祥子的读书笔记
2015/06/26 职场文书
嘉年华活动新闻稿
2015/07/17 职场文书
QT连接MYSQL数据库的详细步骤
2021/07/07 MySQL
python机器学习创建基于规则聊天机器人过程示例详解
2021/11/02 Python
超越Nginx的Web服务器caddy优雅用法
2022/06/21 Servers