php简单使用shmop函数创建共享内存减少服务器负载
在之前的一篇博客[了解一下共享内存的概念及优缺点]已经对共享内存的概念做了说明。下面就来简单使用共享内存(其实也可以用其他工具,比如redis)
PHP做内存共享有两套接口。一个是shm,它实际上是变量共享,会把对象变量序列化后再储存。使用起来倒是挺方便,但是序列化存储对于效率优先的内存访问操作而言就没啥意义了。另外一个是shmop,它是Linux和Windows通用的,不过功能上比shm弱了一些,在 Linux 上,这些函数直接是通过调用 shm* 系列的函数实现,而 Winodows 上也通过对系统函数的封装实现了同样的调用。我这里先用的是shmop。
要创建共享内存段需要使用函数shmop,那么前提需要开启扩展,可以参考[给PHP开启shmop扩展实现共享内存].
shmop主要函数
shmop_open (创建或打开共享内存块)、shmop_write (向共享内存块中写入数据)、shmop_read (从共享内存块中读取数据)、shmop_size (获取共享内存块的大小)、shmop_close (关闭共享内存块)、shmop_delete (删除共享内存块)
<?php //创建一块共享内存 $shm_key = 0x4337b101; $shm_id = @shmop_open($shm_key, 'c', 0644, 1024); //读取并写入数据 $data = shmop_read($shm_id, 0, 1024); shmop_write($shm_id, json_encode($data), 0); $size = shmop_size($shm_id); //获取内存中实际数据占用大小 //关闭内存块,并不会删除共享内存,只是清除 PHP 的资源 shmop_close($shm_id);
shmop_open(创建内存段)
该函数中出现的第一个事物是系统 ID 参数。这是标识系统中的共享内存段的数字。第二个参数是访问模式,它非常类似于 fopen 函数的访问模式。您可以在 4 种不同的模式下访问一个内存段:
模式 “a”,它允许您访问只读内存段,只读访问
模式 “w”,它允许您访问可读写的内存段,读写
模式 “c”,它创建一个新内存段,或者如果该内存段已存在,尝试打开它进行读写
模式 “n”,它创建一个新内存段,如果同样 key 的已存在,则会创建失败,这是为了安全使用共享内存考虑。
第三个参数是内存段的权限。您必须在这里提供一个八进制值。
第四个参数提供内存段大小,以字节为单位。由于使用的共享内存片段是固定长度的,在存储和读取的时候要计算好数据的长度,不然可能会写入失败或者读取空值。。
请注意,此函数返回一个 ID 编号,其他函数可使用该 ID 编号操作该共享内存段。这个 ID 是共享内存访问 ID,与系统 ID 不同,它以参数的形式传递。请注意不要混淆这两者。如果失败,shmop_open 将返回 FALSE。在创建内存块时建议key参数用常量而不用变量,否则很有可能造成内存泄露。
shmop_write(向内存段写入数据)
这个函数类似于 fwrite 函数,后者有两个参数:打开的流资源(由 fopen 返回)和您希望写入的数据。shmop_write 函数也执行此任务。
第一个参数是 shmop_open 返回的 ID,它识别您操作的共享内存块。第二个参数是您希望存储的数据,最后的第三个参数是您希望开始写入的位置。默认情况下,我们始终使用 0 来表示开始写入的位置。请注意,此函数在失败时会返回 FALSE,在成功时会返回写入的字节数。
shmop_read(从内存段读取数据)
从共享内存段读取数据很简单。您只需要一个打开的内存段和 shmop_read 函数。此函数接受一些参数,工作原理类似于 fread。
请留意这里的参数。shmop_read 函数将接受 shmop_open 返回的 ID,我们已知道它,不过它还接受另外两个参数。第二个参数是您希望从内存段读取的位置,而第三个是您希望读取的字节数。第二个参数可以始终为 0,表示数据的开头,但第三个参数可能存在问题,因为我们不知道我们希望读取多少字节。
这非常类似于我们在 fread 函数中的行为,该函数接受两个参数:打开的流资源(由 fopen 返回)和您希望从该流读取的字节数。使用 filesize 函数(它返回一个文件中的字节数)来完整地读取它。
shmop_size(返回内存段数据实际大小)
比如,我们开辟了一个长度为100字节的内存空间,但是实际存入的数据长度仅仅90,那么使用shmop_size返回的值就是90.
shmop_delete(删除内存段)
该函数仅接受一个参数:我们希望删除的共享内存 ID,这不会实际删除该内存段。它将该内存段标记为删除,因为共享内存段在有其他进程正在使用它时无法被删除。shmop_delete 函数将该内存段标记为删除,阻止任何其他进程打开它。要删除它,我们需要关闭该内存段。在创建内存块时建议key参数用常量而不用变量,否则很有可能造成内存泄露。
shmop_close(关闭内存段)
我们在对内存段进行读取和写入,但完成操作后,我们必须从它解除,这非常类似于处理文件时的 fclose 函数。打开包含一个文件的流并在其中读取或写入数据后,我们必须关闭它,否则将发生锁定。
简单测试结果查看
我是在LNMP环境下操作的,如果你也和我一样,在执行完简单的操作之后,可以使用linux命令查看一下地址和占用大小
# ipcs -m
[root@bogon ~]# ipcs -m------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 0 gdm 600 393216 2 dest 0x00000000 32769 gdm 600 393216 2 dest 0x4337b101 884750 nobody 644 1024 0
命令说明
key :共享内存的唯一的key值,共享内存通过该key来判断你读取的是哪一块内存。
shmid:当使用key来获取内存时,你获得的是这个id的值。它作为你操作内存块的标识。
owner:创建该共享内存块的用户
perms:该共享内存的读写权限,8禁止,可以是777,与文件的读写权限一致。
bytes:该内存块的大小
nattch:连接该内存块的进程数
status:当前状态,如:dest,即将删除等。
项目实际应用小案例
/*** 将领技能*/ class Generalskill_model extends CI_Model {private $_memory_key = 0x4337b001; //共享内存地址keyprivate $_memory_size = 1048576; //开辟共享内存大小 //最好根据实际数据长度大小定义。public function __construct() {parent::__construct();}public function get_skill_list() {$data = [];$shmid = @shmop_open($this->_memory_key, 'a', 0644, $this->_memory_size); if ($shmid === FALSE) {$shmid = @shmop_open($this->_memory_key, 'c', 0644, $this->_memory_size); $data = $this->return_skill_list();shmop_write($shmid, json_encode($data), 0); @shmop_close($shmid);return $data;}$data = json_decode(preg_replace('/[\x00-\x1F\x80-\x9F]/u', '', trim(shmop_read($shmid, 0, $this->_memory_size))), true);@shmop_close($shmid);return $data; }public function return_skill_list() { //这里是一个超大的数组,其实就是把这个数组json化,然后存入共享内存段。 其实可以用redis等其他缓存...这里我就是为了不用redis等其他nosql才用的shmopreturn array (1 => array ('id' => '1','animation' => '13','skill_type' => '1','power_type' => '1','site' => '1','type' => '1','paramete' => '0','paramete2' => '0','paramete3' => '0','chance' => '0','ratio' => '1',),2 => array ('id' => '2','animation' => '3','skill_type' => '2','power_type' => '1','site' => '1','type' => '1','paramete' => '0','paramete2' => '0','paramete3' => '0','chance' => '0','ratio' => '2',),..........................................
当然你要考虑的是,如果数据更新的话,那么内存段也要删除,并且更新数据......................通过shmop_delete可以删除 。这就需要你们自己根据项目应用来考虑了
还有就是我这里只是为了简单的读,并没有出现复杂的读写,否则可能会出现进程互斥等意想不到的冲突~如果复杂,那么就可以考虑信号量了~
如果你在项目中遇到主从场景。可以参考这篇文章 http://tubaluer.iteye.com/blog/1349797
转载于:https://www.cnblogs.com/wt645631686/p/9130764.html
php简单使用shmop函数创建共享内存减少服务器负载相关推荐
- php windows共享内存,给PHP开启shmop扩展实现共享内存
这篇文章主要介绍了关于给PHP开启shmop扩展实现共享内存,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 在项目开发中,想要实现PHP多个进程之间共享数据的功能,让客户端连接能够共享 ...
- linux如何创建共享内存,linux实现共享内存同步的四种方法
https://blog.csdn.net/sunxiaopengsun/article/details/79869115 本文主要对实现共享内存同步的四种方法进行了介绍. 共享内存是一种最为高效的进 ...
- Linux下的共享内存 ---创建共享内存
说明: 1.创建共享内存使用的函数:int shmget(key_t key, size_t size, int shm-flg); 2.参数key既可以是IPC_PRIVATE(0),也可是是fto ...
- shmget创建共享内存errno - ipcs - From
Thanks to: https://blog.csdn.net/libaineu2004/article/details/76919711 今天编写的程序,要使用一个共享内存,共享内存是由别的进程创 ...
- mmp函数(共享内存映射)使用方法以及注意事项
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 创建共享内存映射 参数: addr: ...
- PHP IPC函数介绍---共享内存
以下是php的共享内存常用函数,用于进程间的通信 shm_attach - Creates or open a shared memory segment shm_detach - Disconnec ...
- 【Python】简单的最优算法函数创建
基于Python的算法函数创建 题目1:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的两位数?都是多少? 该题目不用创建函数 n = 0 # 计数变量 for i in range(1,5 ...
- 修改服务器的共享内存大小,服务器共享内存大小能改么
服务器共享内存大小能改么 内容精选 换一换 开发者板形态下,使用16路推理进程并发对1080P图片进行处理,导致内存耗尽,内存申请失败后进程退出.为了防止抖动,默认情况下Engine队列大小为200, ...
- linux存储--共享内存机制shm(十四)
共享存储允许两个或多个进程共享一个给定的存储区,是进程间通信最快的一种方式. 不要同时对共享存储空间进行写操作,通常,信号量用于同步共享存储访问. 最简单的共享内存的使用流程 ①ftok函数生成键值 ...
- 【Linux】进程间通信-共享内存
前言 我们知道,在Linux中,进程是相互独立存在的,不存在直接让进程之间互相通信的方式.但是如果我们能让不同进程之间见到同一块内存,也就是都能读写这片区域是不是就能够达到进程间通信呢? 事实证明确实 ...
最新文章
- mysql 1449 : The user specified as a definer ('root'@'%') does not exist
- linux安装manjaro创建分区失败,如何安装Manjaro Linux [最强指南]? 看完就知道了
- 时间序列交叉验证TimeSeriesSplit
- 恐鬼症不显示服务器区域,恐鬼症 steam版【简体中文】【4.34GB】
- 13 张图带你学懂 Kubernetes Service(转载)
- 数学对编程思想的帮助_学编程需要什么基础?
- vue+node+mongodb实现的功能
- python求曲线拐点_如何发现拐点?
- IDEA 部署 Java Web 应用为 war 包
- springboot的Interceptor、Filter、Listener及注册
- 龙芯mips64 Javajdk下载
- 利用WPS的Excel制作项目进度表
- 微信小程序教程、开发资源下载汇总(2.8日更新,持续更新中……)
- 通信专业顶刊_通信方面的期刊_信息与通信工程期刊排行顶级的_通信技术
- 用计算机三角函数公式,三角函数公式习题.doc
- Redisson读写锁
- 吃鸡一直显示服务器,吃鸡一直显示服务器未连接 | 手游网游页游攻略大全
- 用计算机打出刚好遇见你,【计算机·故事】刚好遇见你 余生都是你
- 学习并使用HC-SR04超声波测距模块+STM32
- 中国Linux早期历史的回眸
热门文章
- [渝粤教育] 天水师范学院 离散数学 参考 资料
- window-linux移植
- Prophet模型预测商品销售量
- CString转char*的两种方法讨论
- 【5分钟Paper】Fast强化学习和Slow强化学习
- 【5分钟paper】基于强化学习的策略搜索算法的自主直升机控制
- 系统类配置(五)【ubuntu14.04下安装cuda8+nvidia-410.78+cudnn6.0 +tensorflow-gpu==1.4.0。】
- Airbnb 面试题汇总
- Search Insert Position - LeetCode
- [转]英特尔为什么能在CPU方面领跑?