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 相关文章推荐
一些常用的php简单命令代码集锦
Sep 24 PHP
php中取得文件的后缀名?
Feb 20 PHP
JS中encodeURIComponent函数用php解码的代码
Mar 01 PHP
解析php DOMElement 操作xml 文档的实现代码
May 10 PHP
PHP的MVC模式实现原理分析(一相简单的MVC框架范例)
Apr 29 PHP
50个PHP程序性能优化的方法
Jun 02 PHP
PHP连接sql server 2005环境配置及问题解决
Aug 08 PHP
PHP实现批量修改文件后缀名的方法
Jul 30 PHP
表单提交错误后返回内容消失问题的解决方法(PHP网站)
Oct 20 PHP
PHP使用trim函数去除字符串左右空格及特殊字符实例
Jan 07 PHP
PHP执行shell脚本运行程序不产生core文件的方法
Dec 28 PHP
Laravel框架在本地虚拟机快速安装的方法详解
Jun 11 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
咖啡冲泡指南 咖啡有哪些制作方式 单品咖啡 意式咖啡
2021/03/06 冲泡冲煮
一个经典的PHP文件上传类分享
2014/11/18 PHP
PHP session文件独占锁引起阻塞问题解决方法
2015/05/12 PHP
WordPress中编写自定义存储字段的相关PHP函数解析
2015/12/25 PHP
seajs1.3.0源码解析之module依赖有序加载
2012/11/07 Javascript
JavaScript中Function()函数的使用教程
2015/06/04 Javascript
12种JavaScript常用的MVC框架比较分析
2015/11/16 Javascript
JS在Array数组中按指定位置删除或添加元素对象方法示例
2019/11/19 Javascript
在vue中使用Echarts利用watch做动态数据渲染操作
2020/07/20 Javascript
vue实现虚拟列表功能的代码
2020/07/28 Javascript
利用js canvas实现五子棋游戏
2020/10/11 Javascript
[原创]使用豆瓣提供的国内pypi源
2017/07/02 Python
Python数据结构之单链表详解
2017/09/12 Python
windows下 兼容Python2和Python3的解决方法
2018/12/05 Python
python批量获取html内body内容的实例
2019/01/02 Python
如何通过雪花算法用Python实现一个简单的发号器
2019/07/03 Python
opencv3/C++实现视频读取、视频写入
2019/12/11 Python
Python实现i人事自动打卡的示例代码
2020/01/09 Python
利用Vscode进行Python开发环境配置的步骤
2020/06/22 Python
python 绘制场景热力图的示例
2020/09/23 Python
Python3 用什么IDE开发工具比较好
2020/11/28 Python
使用HTML5的File实现base64和图片的互转
2013/08/01 HTML / CSS
Ann Taylor官方网站:美国最大的女性产品制造商之一
2016/09/14 全球购物
Joe Fresh官网:加拿大时尚品牌和零售连锁店
2016/11/30 全球购物
新西兰最大的品牌运动鞋购物网站:Platypus NZ
2017/10/27 全球购物
EVE LOM英国官网:全世界最好的洁面膏
2017/10/30 全球购物
英国第一职业高尔夫商店:Clickgolf.co.uk
2020/11/18 全球购物
大学学习生活感言
2014/01/18 职场文书
2014自主招生自荐信策略
2014/01/27 职场文书
幸福家庭事迹材料
2014/02/03 职场文书
裁员通知
2015/04/25 职场文书
员工年度工作总结2015
2015/05/18 职场文书
当幸福来敲门观后感
2015/06/01 职场文书
小爸爸观后感
2015/06/15 职场文书
致运动员赞词
2015/07/22 职场文书
干货:如何写好观后感 !
2019/05/21 职场文书