PHP共享内存使用与信号控制实例分析


Posted in PHP onMay 09, 2018

本文实例讲述了PHP共享内存使用与信号控制。分享给大家供大家参考,具体如下:

共享内存

共享内存的使用主要是为了能够在同一台机器不同的进程中共享一些数据,比如在多个 php-fpm 进程中共享当前进程的使用情况。这种通信也称为进程间通信(Inter-Process Communication),简称 IPC。

PHP 内置的 shmop 扩展 (Shared Memory Operations) 提供了一系列共享内存操作的函数(可能是用的人不多吧,这一块儿的文档还没有中文翻译)。在 Linux 上,这些函数直接是通过调用 shm* 系列的函数实现,而 Winodows 上也通过对系统函数的封装实现了同样的调用。

主要函数:

shmop_close — 关闭共享内存块

shmop_delete — 删除共享内存块

shmop_open — 创建或打开共享内存块

shmop_read — 从共享内存块中读取数据

shmop_size — 获取共享内存块的大小

shmop_write — 向共享内存块中写入数据

与此相关的还有一个很重要的函数:ftok,通过文件的 inode 信息(*nix 上通过 stat 或 ls -i 命令查看)创建 IPC 的唯一 key(文件/文件夹的 inode 是唯一的)。这个函数在 Linux 上也是直接调用同名的系统函数实现,Windows 上还是使用一些封装。

一个简单的计数例子:

<?php
# 创建一块共享内存
$shm_key = ftok(__FILE__, 't');
$shm_id = shmop_open($shm_key, 'c', 0644, 8);
# 读取并写入数据
$count = (int) shmop_read($shm_id, 0, 8) + 1;
shmop_write($shm_id, str_pad($count, 8, '0', STR_PAD_LEFT), 0);
// echo shmop_read($shm_id, 0, 8);
# 关闭内存块,并不会删除共享内存,只是清除 PHP 的资源
shmop_close($shm_id);

以上这段代码没执行一次计数加 1,而且数据是在不同进程之间共享的。也就是说除非手动删除这块内存使用,否则这个数据是不会重置的。

有个需要稍微注意的点:shmop_open 的第二个参数是个 flag,类似 fopen 的第二个参数,其取值有以前几个:

"a" 只读访问;

"c" 如果内存片段不存在,则创建,如果存在,则可读写;

"w" 读写;

"n" 创建新的内存片段,如果同样 key 的已存在,则会创建失败,这是为了安全使用共享内存考虑。

此外,由于使用的共享内存片段是固定长度的,在存储和读取的时候要计算好数据的长度,不然可能会写入失败或者读取空值。

信号控制

既然上面使用到了共享内存存储数据,就需要考虑是否有多个进程同时写入数据到共享内存的情况,是否需要避免冲突。如果是这样,就需要引入信号量进行控制。

PHP 也提供了类似的内置扩展 sysvsem(这个扩展在 Windows 环境下没有,文档中将 ftok 函数也归到这个扩展中,但实际上ftok 是在标准函数库中提供的,所以在 Windows 下也是可用的)。

在说信号量控制之前,先说另外一件有意思的事情:看官方文档你会发现这里同样也有共享内存操作的函数(shm_*),因为这其实是同一类别(或者说来自于同一作者)的三个扩展,还有一个是 sysvmsg(队列消息) 。函数的实现上稍有差别,但实际做的事情基本相同。这和上文的 shmop 扩展有什么区别呢?shmop 源码下的 README 文件有简单的说明:

PHP already had a shared memory extension (sysvshm) written by Christian Cartus <cartus@atrior.de>, unfortunately this extension was designed with PHP only in mind and offers high level features which are extremely bothersome for basic SHM we had in mind.

简单说来:sysvshm 扩展提供的方法并不是原封不动的存储用户的数据,而是先使用 PHP 的变量序列化函数对参数进行序列化然后再进行存储。这就导致通过这些方法存储的数据无法和非 PHP 进程共享。不过这样也能存储更丰富的 PHP 数据类型,上文的扩展中 shmop_write 只能写入字符串。那么为什么 sysvshm 同样不支持 Windows 呢?因为其并没有引入封装了 shm* 系列函数的tsrm_win32.h 的头文件。

引入信号控制之后的示例:

<?php
$id_key = ftok(__FILE__, 't');
$sem_id = sem_get($id_key);
# 请求信号控制权
if (sem_acquire($sem_id)) {
  $shm_id = shmop_open($id_key, 'c', 0644, 8);
  # 读取并写入数据
  $count = (int) shmop_read($shm_id, 0, 8) + 1;
  shmop_write($shm_id, str_pad($count, 8, '0', STR_PAD_LEFT), 0);
  // echo shmop_read($shm_id, 0, 8);
  # 关闭内存块
  shmop_close($shm_id);
  # 释放信号
  sem_release($sem_id);
}

但是本地想模拟实现写入冲突实际上是非常难的(考虑到计算机的执行速度)。在本地测试中,使用 for 循环操作时如果不使用shmop_close 关闭资源会出现无法打开共享内存的错误警告。这应该是因为正在共享内存被上一次操作占用中还没有释放导致。

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
用Zend Encode编写开发PHP程序
Oct 09 PHP
php防攻击代码升级版
Dec 29 PHP
php 面试碰到过的问题 在此做下记录
Jun 09 PHP
PHP里的中文变量说明
Jul 23 PHP
用PHP解决的一个栈的面试题
Jul 02 PHP
PHP中array_map与array_column之间的关系分析
Aug 19 PHP
Yii使用find findAll查找出指定字段的实现方法
Sep 05 PHP
利用Fix Rss Feeds插件修复WordPress的Feed显示错误
Dec 19 PHP
PhpStorm terminal无法输入命令的解决方法
Oct 09 PHP
ThinkPHP框架获取最后一次执行SQL语句及变量调试简单操作示例
Jun 13 PHP
PHP的mysqli_select_db()函数讲解
Jan 23 PHP
ThinkPHP6.0如何利用自定义验证规则规范的实现登陆
Dec 16 PHP
php curl批处理实现可控并发异步操作示例
May 09 #PHP
php使用curl伪造来源ip和refer的方法示例
May 08 #PHP
PHP+ajax实现获取新闻数据简单示例
May 08 #PHP
PHP 计算两个特别大的整数实例代码
May 07 #PHP
详解PHP发送邮件知识点
May 06 #PHP
PHP学习笔记之session
May 06 #PHP
PHP中cookie知识点学习
May 06 #PHP
You might like
php数组的概述及分类与声明代码演示
2013/02/26 PHP
PHP产生不重复随机数的5个方法总结
2014/11/12 PHP
PHP对称加密函数实现数据的加密解密
2016/10/27 PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
2018/06/16 PHP
laravel-admin的图片删除实例
2019/09/30 PHP
用于判断用户注册时,密码强度的JS代码
2009/01/01 Javascript
JQuery循环滚动图片代码
2011/12/08 Javascript
jquery 设置元素相对于另一个元素的top值(实例代码)
2013/11/06 Javascript
让你一句话理解闭包(简单易懂)
2016/06/03 Javascript
JCrop+ajaxUpload 图像切割上传的实例代码
2016/07/20 Javascript
js实现下一页页码效果
2017/03/07 Javascript
Vue-Quill-Editor富文本编辑器的使用教程
2018/09/21 Javascript
layui文件上传控件带更改后数据传值的方法
2019/09/23 Javascript
javascript实现支付宝滑块验证码效果
2020/07/24 Javascript
[01:33]真香警告!DOTA2勇士令状不朽珍藏Ⅱ饰品欣赏
2018/06/26 DOTA
Python使用pandas和xlsxwriter读写xlsx文件的方法示例
2019/04/09 Python
Python类中self参数用法详解
2020/02/13 Python
python GUI库图形界面开发之PyQt5输入对话框QInputDialog详细使用方法与实例
2020/02/27 Python
Python暴力破解Mysql数据的示例
2020/11/09 Python
一款纯css3实现的tab选项卡的实列教程
2014/12/11 HTML / CSS
解决CSS3 transition-delay 属性默认值0不带单位失效的问题
2020/10/29 HTML / CSS
HTML5 placeholder(空白提示)属性介绍
2013/08/07 HTML / CSS
Html5实现用户注册自动校验功能实例代码
2016/05/24 HTML / CSS
海滩咖啡馆:Beach Cafe
2018/02/02 全球购物
Champs Sports加拿大:北美最大的以商场为基础的专业运动鞋和服装零售商之一
2018/05/01 全球购物
在线购买世界上最好的酒:BoozeBud
2018/06/07 全球购物
香港莎莎官网Sasa.com:亚洲著名国际化妆品商城
2019/11/10 全球购物
护理学中专毕业生求职信
2013/11/11 职场文书
合作协议书范文
2014/08/20 职场文书
2015年机械设备管理工作总结
2015/05/04 职场文书
2015年党风廉政建设目标责任书
2015/05/08 职场文书
让世界充满爱观后感
2015/06/10 职场文书
严以用权专题学习研讨会发言材料
2015/11/09 职场文书
读鲁迅先生的经典名言
2019/08/20 职场文书
python源码剖析之PyObject详解
2021/05/18 Python
Python使用永中文档转换服务
2022/05/06 Python