PHP共享内存使用与信号控制实例分析
本文实例讲述了PHP共享内存使用与信号控制。分享给大家供大家参考,具体如下:
共享内存
共享内存的使用主要是为了能够在同一台机器不同的进程中共享一些数据,比如在多个php-fpm进程中共享当前进程的使用情况。这种通信也称为进程间通信(Inter-ProcessCommunication),简称IPC。
PHP内置的shmop扩展(SharedMemoryOperations)提供了一系列共享内存操作的函数(可能是用的人不多吧,这一块儿的文档还没有中文翻译)。在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,而且数据是在不同进程之间共享的。也就是说除非手动删除这块内存使用,否则这个数据是不会重置的。
有个需要稍微注意的点:shmop_open的第二个参数是个flag,类似fopen的第二个参数,其取值有以前几个:
"a"只读访问;
"c"如果内存片段不存在,则创建,如果存在,则可读写;
"w"读写;
"n"创建新的内存片段,如果同样key的已存在,则会创建失败,这是为了安全使用共享内存考虑。
此外,由于使用的共享内存片段是固定长度的,在存储和读取的时候要计算好数据的长度,不然可能会写入失败或者读取空值。
信号控制
既然上面使用到了共享内存存储数据,就需要考虑是否有多个进程同时写入数据到共享内存的情况,是否需要避免冲突。如果是这样,就需要引入信号量进行控制。
PHP也提供了类似的内置扩展sysvsem(这个扩展在Windows环境下没有,文档中将ftok函数也归到这个扩展中,但实际上ftok是在标准函数库中提供的,所以在Windows下也是可用的)。
在说信号量控制之前,先说另外一件有意思的事情:看官方文档你会发现这里同样也有共享内存操作的函数(shm_*),因为这其实是同一类别(或者说来自于同一作者)的三个扩展,还有一个是sysvmsg(队列消息)。函数的实现上稍有差别,但实际做的事情基本相同。这和上文的shmop扩展有什么区别呢?shmop源码下的README文件有简单的说明:
PHPalreadyhadasharedmemoryextension(sysvshm)writtenbyChristianCartus
,unfortunatelythisextensionwasdesignedwithPHPonlyinmindandoffershighlevelfeatureswhichareextremelybothersomeforbasicSHMwehadinmind. 简单说来:sysvshm扩展提供的方法并不是原封不动的存储用户的数据,而是先使用PHP的变量序列化函数对参数进行序列化然后再进行存储。这就导致通过这些方法存储的数据无法和非PHP进程共享。不过这样也能存储更丰富的PHP数据类型,上文的扩展中shmop_write只能写入字符串。那么为什么sysvshm同样不支持Windows呢?因为其并没有引入封装了shm*系列函数的tsrm_win32.h的头文件。
引入信号控制之后的示例:
但是本地想模拟实现写入冲突实际上是非常难的(考虑到计算机的执行速度)。在本地测试中,使用for循环操作时如果不使用shmop_close关闭资源会出现无法打开共享内存的错误警告。这应该是因为正在共享内存被上一次操作占用中还没有释放导致。
更多关于PHP相关内容感兴趣的读者可查看本站专题:《PHP基本语法入门教程》、《PHP错误与异常处理方法总结》、《php程序设计算法总结》及《php面向对象程序设计入门教程》
希望本文所述对大家PHP程序设计有所帮助。