• 售前

  • 售后

热门帖子
入门百科

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

[复制链接]
123457595 显示全部楼层 发表于 2021-10-25 19:57:11 |阅读模式 打印 上一主题 下一主题
本文实例讲述了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 上还是使用一些封装。
一个简朴的计数例子:
  1. <?php
  2. # 创建一块共享内存
  3. $shm_key = ftok(__FILE__, 't');
  4. $shm_id = shmop_open($shm_key, 'c', 0644, 8);
  5. # 读取并写入数据
  6. $count = (int) shmop_read($shm_id, 0, 8) + 1;
  7. shmop_write($shm_id, str_pad($count, 8, '0', STR_PAD_LEFT), 0);
  8. // echo shmop_read($shm_id, 0, 8);
  9. # 关闭内存块,并不会删除共享内存,只是清除 PHP 的资源
  10. 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 的头文件。
引入信号控制之后的示例:
  1. <?php
  2. $id_key = ftok(__FILE__, 't');
  3. $sem_id = sem_get($id_key);
  4. # 请求信号控制权
  5. if (sem_acquire($sem_id)) {
  6.   $shm_id = shmop_open($id_key, 'c', 0644, 8);
  7.   # 读取并写入数据
  8.   $count = (int) shmop_read($shm_id, 0, 8) + 1;
  9.   shmop_write($shm_id, str_pad($count, 8, '0', STR_PAD_LEFT), 0);
  10.   // echo shmop_read($shm_id, 0, 8);
  11.   # 关闭内存块
  12.   shmop_close($shm_id);
  13.   # 释放信号
  14.   sem_release($sem_id);
  15. }
复制代码
但是本地想模拟实现写入辩说实际上黑白常难的(思量到计算机的执行速率)。在本地测试中,使用 for 循环操纵时如果不使用shmop_close 关闭资源会出现无法打开共享内存的错误告诫。这应该是因为正在共享内存被上一次操纵占用中还没有开释导致。
更多关于PHP相干内容感兴趣的读者可查看本站专题:《PHP基本语法入门教程》、《PHP错误与异常处理方法总结》、《php步调设计算法总结》及《php面向对象步调设计入门教程》
盼望本文所述对大家PHP步调设计有所资助。

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作