单台服务器的PHP进程之间实现共享内存的方法


Posted in PHP onJune 13, 2014

开发人员要想使php进程实现共享内存的读写,首先就要支持IPC函数,即php编译安装时指定:--enable-shmop  与--enable-sysvsem 两个选项

IPC (Inter-process communication) 是一个Unix标准机制,它提供了使得在同一台主机不同进程之间可以互相的方法。基本的IPC处理机制有3种:它们分别是共享内存、信号量和消息队列。本文中我们主要讨论共享内存和信号量的使用。

在不同的处理进程之间使用共享内存是一个实现不同进程之间相互的好方法。如果你在一个进程中向所共享的内存写入一段信息,那么所有其他的进程也可以看到这段被写入的数据。非常方便。在PHP中有了共享内存的帮助,你可以实现不同进程在运行同一段PHP脚本时返回不同的结果。或实现对PHP同时运行数量的实时查询等等。

共享内存允许两个或者多个进程共享一给定的存储区。因为数据不需要在客户机和服务器之间复制,所以这是最快的一种IPC。使用共享内存的唯一窍门是多个进程对一给定存储区的同步存取。

如何建立一个共享内存段呢?下面的代码可以帮你建立共享内存。

$shm_id = shmop_open($key, $mode, $perm, $size);

注意,每个共享内存段都有一个唯一的ID, 在PHP中,shmop_open会把建立好的共享内存段的ID返回,这里我们用$shm_id记录它。而$key是一个我们逻辑上表示共享内存段的Key值。不同进程只要选择同一个Key id就可以共享同一段存储段。习惯上我们用一个串(类似文件名一样的东西)的散列值作为key id. $mode指明了共享内存段的使用方式。这里由于是新建,因此值为'c' ?取create之意。如果你是已经建立过的共享内存那么请用'a', 取access之意。$perm参数定义了的权限,8进制,关于权限定义请看UNIX文件系统帮助。$size定义了共享内存的大小。尽管有点象fopen(文件处理)你可不要当它同文件处理一样。后面的描述你将看到这一点。

例如:

$shm_id = shmop_open(0xff3, "c", 0644, 100);

这里我们打开了一个共享内存段 键值0xff3 ?rw-r—r—格式,大小为100字节。

如果需要已有的共享内存段,你必须在调用shmop_open中设第3、4个参数为0。

在Unix下,你可以用一个命令行程序ipcs查询系统所有的IPC资源状态。不过有些系统要求需要超级用户方能执行。下图是一段ipcs的运行结果。

上图中系统显示了4个共享内存段,注意其中第4个键值为0x00000ff3的就是我们刚刚运行过的PHP程序所创建的。关于ipcs的用法请参考UNIX用户手册。

如何释放共享内存呢

释放共享内存的办法是调用PHP指令:shmop_delete($id)

shmop_delete($id);

$id 就是你调用shmop_open所存的shmop_op的返回值。还有一个办法就是用UNIX的管理指令:

ipcrm id, id就是你用ipcs看到的ID.和你程序中的$id不一样。不过要小心,如果你用ipcrm直接删除共享内存段那么有可能导致其他不知道这一情况的进程在引用这个已经不复存在的共享内存器时出现一些不可预测的错误(往往结果不妙)。

如何使用(读写)共享内存呢

使用如下所示函数向共享内存写入数据

int shmop_write (int shmid, string data, int offset)

其中shmid是用shmop_open返回的句柄。$Data变量存放了要存放的数据。$offset描述了写入从共享内存的开始第一个字节的位置(以0开始)。

读取操作是:

string shmop_read (int shmid, int start, int count)

同样,指明$shmid,开始偏移量(以0开始)、总读取数量。返回结果串。这样,你就可以把共享内存段当作是一个字节数组。读几个再写几个,想干嘛就干嘛,十分方便。

现在,在单独的一个PHP进程中读写、创建、删除共享内存方面上你应该没有问题了。但是,显然实际运行中不可能只是一个PHP进程在运行中。如果在多个进程的情况下你还是沿用单个进程的处理方法,你一定会碰到问题--著名的并行和互斥问题。比如说有2个进程同时需要对同一段内存进行读写。当两个进程同时执行写入操作时,你将得到一个错误的数据,因为该段内存将之可能是最后执行的进程的内容,甚至是由2个进程写入的数据轮流随机出现的一段混合的四不象。这显然是不能接受的。为了解决这个问题,我们必须引入互斥机制。互斥机制在很多操作系统的教材上都有专门讲述,这里不多重复。实现互斥机制的最简单办法就是使用信号灯。信号量是另外一种进程间(IPC)的方式,它同其他IPC机构(管道、FIFO、消息队列)不同。它是一个记数器,用于控制多进程对共享数据的存储。同样的是你可以用ipcs和ipcrm实现对信号灯使用状态的查询和对其实现删除操作。在PHP中你可以用下列函数创建一个新的信号量并返回操作该信号量的句柄。如果该key指向的信号量已经存在,sem_get直接返回操作该信号量的句柄。

int sem_get(int key [, int max_acquire [, int perm]])

$max_acquire 指明同时最多可以用几个进程进入该信号而不必等待该信号被释放(也就是最大同时处理某一资源的进程数目,一般该值均为一)。$perm指明了权限。

一旦你成功的拥有了一个信号量,你对它所能做的只有2种:请求、释放。当你执行释放操作时, 系统将把该信号值减一。如果小于0那就还设为0。而当你执行请求操作时,系统将把该信号值加一,如果该值大于设定的最大值那么系统将挂起你的处理进程直到其他进程释放到小于最大值为止。一般情况下最大值设为1,这样一来当一个进程获得请求时其他后面的进程只能等待它退出互斥区后释放信号量才能进入该互斥区并同时设为独占方式。这样的信号量常称为双态信号量。当然,如果初值是任意一个正数就表明有多少个共享资源单位可供共享应用。

PHP 相关文章推荐
PHP 和 COM
Oct 09 PHP
PHP编程之高级技巧——利用Mysql函数
Oct 09 PHP
CI框架安全类Security.php源码分析
Nov 04 PHP
PHP记录搜索引擎蜘蛛访问网站足迹的方法
Apr 15 PHP
php简单统计在线人数的方法
May 10 PHP
详解WordPress中添加友情链接的方法
May 21 PHP
php利用嵌套数组拼接与解析json的方法
Feb 07 PHP
php7基于递归实现删除空文件夹的方法示例
Jun 15 PHP
yii2多图上传组件的使用教程
May 10 PHP
Laravel5框架自定义错误页面配置操作示例
Apr 17 PHP
浅析PHP7 的垃圾回收机制
Sep 06 PHP
laravel5.1 ajax post 传值_token示例
Oct 24 PHP
PHPAnalysis中文分词类详解
Jun 13 #PHP
ThinkPHP缓存方法S()概述
Jun 13 #PHP
采用ThinkPHP中F方法实现快速缓存实例
Jun 13 #PHP
浅析ThinkPHP中execute和query方法的区别
Jun 13 #PHP
采用thinkphp自带方法生成静态html文件详解
Jun 13 #PHP
PHP中使用gettext解决国际化问题的例子(i18n)
Jun 13 #PHP
Yii结合CKEditor实现图片上传功能
Jun 13 #PHP
You might like
PHILIPS L4X25T电路分析和打理
2021/03/02 无线电
PHP中调用JAVA
2006/10/09 PHP
php5 pdo新改动加载注意事项
2008/09/11 PHP
解析crontab php自动运行的方法
2013/06/24 PHP
TP5框架页面跳转样式操作示例
2020/04/05 PHP
基于Jquery的表格隔行换色,移动换色,点击换色插件
2010/12/22 Javascript
Dom操作之兼容技巧分享
2011/09/20 Javascript
javascript校验价格合法性实例(必须输入2位小数)
2014/05/05 Javascript
jQuery 隐藏和显示 input 默认值示例
2014/06/03 Javascript
各种选择框jQuery的选中方法(实例讲解)
2017/06/27 jQuery
Javascript实现时间倒计时效果
2017/07/15 Javascript
vue 插值 v-once,v-text, v-html详解
2018/01/19 Javascript
jQuery扩展方法实现Form表单与Json互相转换的实例代码
2018/09/05 jQuery
javascript中的this作用域详解
2019/07/15 Javascript
layui table复选框禁止某几条勾选的实例
2019/09/20 Javascript
[31:33]2014 DOTA2国际邀请赛中国区预选赛 TongFu VS DT 第一场
2014/05/23 DOTA
[54:53]完美世界DOTA2联赛PWL S2 GXR vs PXG 第二场 11.18
2020/11/18 DOTA
详细介绍Python语言中的按位运算符
2013/11/26 Python
将字典转换为DataFrame并进行频次统计的方法
2018/04/08 Python
不到20行代码用Python做一个智能聊天机器人
2019/04/19 Python
python 函数中的内置函数及用法详解
2019/07/02 Python
pyinstaller打包opencv和numpy程序运行错误解决
2019/08/16 Python
解决Keras 与 Tensorflow 版本之间的兼容性问题
2020/02/07 Python
Pycharm配置PyQt5环境的教程
2020/04/02 Python
JupyterNotebook 输出窗口的显示效果调整方法
2020/04/13 Python
python开根号实例讲解
2020/08/30 Python
浅谈cookie和localStorage那些事
2019/08/27 HTML / CSS
Baracuta官方网站:Harrington夹克,G9,G4,G10等
2018/03/06 全球购物
New Balance澳大利亚官网:运动鞋和健身服装
2019/02/23 全球购物
青年创业培训欢迎词
2014/01/10 职场文书
消防安全汇报材料
2014/02/08 职场文书
大学活动总结模板
2014/07/10 职场文书
2014党员学习《反腐倡廉警示教育读本》思想汇报
2014/09/13 职场文书
客户答谢会致辞
2015/01/20 职场文书
2016年植树节红领巾广播稿
2015/12/17 职场文书
Python OpenCV超详细讲解调整大小与图像操作的实现
2022/04/02 Python