PHP多进程 - PHP操作共享内存(队列,共享内存段,信号量)

Linux下的共享内存有三种方式:sysv,posix,mmap。但是php只提供了操作sysv的函数,所以下面要说的就是sysv的共享内存,Linux系统提供了三个工具来满足IPC通讯:消息队列,共享内存段,信号量。

ipcs 命令

root@localhost:/usr/local/bin# ipcs

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

PHP提供的扩展,不需要安装,但是需要手动开启。

shmop 共享内存,只能按字节操作
sysvsem 信号量
sysvshm 共享内存,和 shmop 的差别是提供的操作函数不同,支持 key、value操作
sysvmsg 消息队列

sysvsem,sysvshm,sysvmsg 的函数列表
在这里插入图片描述
shmop 的函数列表
在这里插入图片描述
看来 sysvshm 扩展和 shmop 扩展功能差不多。

sysvshm 扩展提供的方法在存储之前对用户的数据进行serialize处理,这里就导致这个存储的数据是无法与其它语言共享的,这一系列方法是php only的方法。

shmop系列函数,虽然能实现共享内存操作,但实际上底层实现非常简陋。一方面底层根本没有加锁,如果你要在并发环境中使用,需要自行实现锁的操作。另外,底层实际上是一个链表结构,数据较多时,查询性能非常差。

无论是Linux还是Windows,都会提供一定大小的内存给应用程序来使用,共享内存就像一个设置了权限的文件,允许你像操作文件一样操作共享内存。

比如,PHP多进程之间的通讯,你可以使用临时文件,管道,或者共享内存来在进程间交换数据;并且,你也可以通过共享内存来实现不同应用程序间的通讯。

1、查看已设置的共享内存中的内存段列表
ipcs -m

------------ 共享内存段 --------------
键key       shmid      拥有者owner  	权限perms   字节bytes    nattch     状态status      
0x00000360 	0          root     	755      	1024    	0 

以上是有可用的片段的情况,是不是和文件的形式很相似。

字段解释:

key 	:共享内存的唯一的key值,共享内存通过该key来判断你读取的是哪一块内存。
shmid	:当使用key来获取内存时,你获得的是这个id的值。它作为你操作内存块的标识,类型为 resource(4) of type (shmop)
owner	:创建该共享内存块的用户
perms	:该共享内存的读写权限,8禁止,可以是777,与文件的读写权限一致。
bytes	:该内存块的大小,字节
nattch	:连接该内存块的进程数
status	:当前状态,如:dest,即将删除等。

key是一个16进制值,我们也可以传10进制值

一般操作:通过key来打开一个内存段,返回shmid,之后通过这个shmid来操作内存段。

查看系统共享内存大小

cd /proc/sys/kernel
cat shmmax

删除共享内存块
ipcrm -m shmid
或者
ipcrm -M key

shmop 系列函数
PHP通过shmop函数来操作共享内存,非常之方便。

shmop_open()
	它允许您打开一个现有的内存段或创建一个新内存段。此函数非常类似于经典的fopen函数.
	$shmid = shmop_open(864, 'c', 0755, 1024);

	第一个参数就是上面的key,如果不存在就会创建,十进制的 864 就是16进制的 0x00000360,都可以使用。返回值就是shmid,失败返回FALSE
	第二个参数是访问模式
		模式 “a”,它允许您访问只读内存段
		模式 “w”,它允许您访问可读写的内存段
		模式 “c”,它创建一个新内存段,或者如果该内存段已存在,尝试打开它进行读写
		模式 “n”,它创建一个新内存段,如果该内存段已存在,则会失败
	第三个参数为权限
	第四个参数为大小,字节

shmop_write()
	写入数据,失败时会返回 FALSE,在成功时会返回写入的字节数。
	shmop_write($shmid, "Hello World!", 0);
	第三个参数为offset

shmop_read()
	读取共享内存数据
	$str = shmop_read($shmid, 0, 11);// offset, length

shmop_size()
	获取指定片段的内存大小,字节
	$size = shmop_size($shmid);

shmop_delete()
	标记为删除,阻止任何其他进程打开它,并没有实际删除。因为本进程正在打开该片段,需要关闭后才会实际被删除。

shmop_close()
	关闭内存段。

实例:
文件1

$shmid = shmop_open(864, 'c', 0755, 1024);// 0x00000360
shmop_write($shmid, "Hello World PHP!", 0); // 注意 data是字符串类型,不管你赋值的是不是字符串。
shmop_close($shmid);

查看

ipcs -m

文件2

$shmid = shmop_open(864, 'c', 0755, 1024);// 0x00000360
var_dump($shmid);// resource(4) of type (shmop)
$size = shmop_size($shmid);
echo shmop_read($shmid, 0, $size) . PHP_EOL;
shmop_close($shmid);

当然,也可以使用其他程序打开,比如java, c++等

并发的问题
共享内存的操作并不是原子性的,多个进程同时操作就存在并发的问题,需要通过信号量来加锁。

在共享数据方面,效率最高的是内存,其次是本地问文件,最慢的是网络IO(memcache, redis,mysql等)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值