作为phper既然了解共享内存函数shmop的使用方法,那么就必须要了解一下信号量是什么,以及信号量使用的代码案例
在单独的一个PHP进程中读写、创建、删除共享内存方面上你应该没有问题了。但是实际运行中不可能只是一个PHP进程在运行中。如果在多个进程的情况下你还是沿用单个进程的处理方法,你一定会碰到问题--著名的并行和互斥问题。比如说有2个进程同时需要对同一段内存进行读写。当两个进程同时执行写入操作时,你将得到一个错误的数据,因为该段内存将之可能是最后执行的进程的内容,甚至是由2个进程写入的数据轮流随机出现的一段混合的四不象。这显然是不能接受的。为了解决这个问题,我们必须引入互斥机制。互斥机制在很多操作系统的教材上都有专门讲述,这里不多重复。实现互斥机制的最简单办法就是使用信号灯。信号量是另外一种进程间(IPC)的方式,它同其他IPC机构(管道、FIFO、消息队列)不同。
说到信号量可能大家都很陌生,作为php肯定知道mysql、redis中的锁,当然还有php文件锁。说白了就是锁,用来解决进程(线程同步的问题),访问前获取锁(获取不到则等待),访问后释放锁。
信号量的作用就是,考虑是否有多个进程同时写入数据到共享内存的情况,是否需要避免冲突。
举一个生活中的例子:以一个停车场的运作为例。简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。
记得给环境开启两个扩展【enable-shmop --enable-sysvsem】
因为php默认不支持这些函数,所以需要重编译php。如要使用:
System V信号量,编译时加上 –enable-sysvsem
System V共享内存,编译时加上 –enable-sysvshm
System V消息队列,编译时加上 –enable-sysvmsg
Shared Memory,编译时加上 –enable-shmop


信号量系列函数
<?php
//1、创建信号量唯一标识符
$key = 0x4337b101;
//2、创建信号量资源ID
$sem_resouce_id = sem_get($key);
//3、接受信号量
sem_acqure($sem_resource_id);
//4、释放信号量
sem_release($sem_resource_id);
//5、销毁信号量
sem_remove($sem_resource_id);
简单小案例
<?php $key = 0x4337b101;
$sem_id = sem_get($key);
//请求信号控制权
if (sem_acquire($sem_id)) {
$shm_id = shmop_open($key, 'c', , );
//读取并写入数据
$count = (int) shmop_read($shm_id, , ) + ;
shmop_write($shm_id, str_pad($count, , '', STR_PAD_LEFT), );
// echo shmop_read($shm_id, 0, 8);
//关闭内存块
shmop_close($shm_id);
//释放信号
sem_release($sem_id);
}
如果出现报错:Warning: sem_release(): SysV semaphore 140680297324568 (key 0x4337b101) is not currently acquired in /usr/local/nginx/html/index.php on line 38
那是因为没有获得锁~
在Linux下命令观察,查看系统共享内存,信号量,队列
# ipcs

# ipcs -s //单独查看信号量的话,使用ipcs -s命令
稍微复杂的案例
<?php
//创建共享内存区域
$shm_key = ftok(__FILE__, 'a');
$shm_id = shm_attach($shm_key, , ); //var_dump($shm_id);die(); resource(4) of type (sysvshm)
const SHARE_KEY = ;
$child_list = []; //加入信号量
$sem_id = ftok(__FILE__, 'b');
$signal = sem_get($sem_id); //$signal resource(5) of type (sysvsem) for ($i = ; $i < ; $i++) {
$pid = pcntl_fork();
if ($pid == -) {
exit("Fork fail!".PHP_EOL);
} elseif ($pid == ) {
//获取信号量
sem_acquire($signal);
if (shm_has_var($shm_id,SHARE_KEY)) {
$count = shm_get_var($shm_id, SHARE_KEY);
$count++;
//模拟业务处理
$sec = rand(, );
sleep($sec);
shm_put_var($shm_id, SHARE_KEY, $count);
} else {
$count = ;
$sec = rand(, );
sleep($sec);
shm_put_var($shm_id, SHARE_KEY, $count);
} echo "child process: ".getmypid()." is writing! now count is: $count ".PHP_EOL; //释放信号量
sem_release($signal);
exit("child process".getmypid()."end".PHP_EOL);
} else {
$child_list[] = $pid;
}
} while (count($child_list) > ) {
foreach ($child_list as $key => $pid) {
$status = pcntl_waitpid($pid, $status);
if ($status > || $status == -) {
unset($child_list[$key]);
}
}
sleep();
} $count = shm_get_var($shm_id, SHARE_KEY);
echo " $count ".PHP_EOL; //销毁信号量
sem_remove($signal); shm_remove($shm_id);
shm_detach($shm_id);
实际运用中根据场景灵活运用就可以了~
作为phper既然了解共享内存函数shmop的使用方法,那么就必须要了解一下信号量是什么,以及信号量使用的代码案例的更多相关文章
- linux实现共享内存同步的四种方法
https://blog.csdn.net/sunxiaopengsun/article/details/79869115 本文主要对实现共享内存同步的四种方法进行了介绍. 共享内存是一种最为高效的进 ...
- php 共享内存学习(shmop函数)
问题:希望可以在进程间共享变量,为共享数据提供快速访问 解决方案:除了可以使用APC模块,还可以用shmop或System V共享内存 //创建键 //将一个可访问的文件路径名转换为一个可供 shmo ...
- 创建共享内存函数CreateFileMapping()详解
测试创建和打开文件映射的时候老是得到"句柄无效"的错误, 仔细看了MSDN以后才发觉是函数认识不透, 这里把相关的解释翻译出来 HANDLE CreateFileMapping( ...
- C++ 共享内存 函数封装
#pragma once #include <string> #include <wtypes.h> #include <map> using namespace ...
- 给PHP开启shmop扩展实现共享内存
在项目开发中,想要实现PHP多个进程之间共享数据的功能,让客户端连接能够共享一个状态,需要开启共享内存函数shmop.如果预期考虑会遇到这方面需求,那么最好在编译PHP的时候添加--with-shmo ...
- Linux POSIX共享内存方法&ipcs &struct shmid_ds
内容是主进程创建子进程计算斐波那契数列. 其中计算到第几项是有主进程命令行输入. 共享内存段,并且查看了一些信息. 参考操作系统概念第七版 3.10,3.11 关于LINUX C库函数 中的 fpri ...
- c#读写共享内存操作函数封装
原文 c#读写共享内存操作函数封装 c#共享内存操作相对c++共享内存操作来说原理是一样,但是c#会显得有点复杂. 现把昨天封装的读写共享内存封装的函数记录下来,一方面希望给需要这块的有点帮助,另一方 ...
- System V 共享内存 和 系列函数
跟消息队列一样,共享内存也有自己的数据结构,如下: struct shmid_ds { struct ipc_perm shm_perm; /* Ownership and permission ...
- PHP共享内存详解
前言 在PHP中有这么一族函数,他们是对UNIX的V IPC函数族的包装. 它们很少被人们用到,但是它们却很强大.巧妙的运用它们,可以让你事倍功半. 它们包括: 信号量(Semaphores) 共享内 ...
随机推荐
- Apache与Tomcat整合的配置
下载jk连接器地址:http://archive.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/windows/ 把jk连接器即“mod_j ...
- jenkins windows slave 报错ERROR: Error cloning remote repo 'origin'
在slave上是git clone ssh是可以成功的,但是jenkins调用slave节点就报如下错误: ERROR: Error cloning remote repo 'origin' huds ...
- [LeetCode] 610. Triangle Judgement_Easy tag: SQL
A pupil Tim gets homework to identify whether three line segments could possibly form a triangle. Ho ...
- 安装Cuda9.0+cudnn7.3.1+tensorflow-gpu1.13.1
我的安装版本: win10 x64 VS2015 conda python 3.7 显卡 GTX 940mx Cuda 9.0 cudnn v7.3.1 Tensorflow-gpu 1.13.1 1 ...
- jquery简介未完成
jQuery jQuery是一个快速.简洁的javascript框架,是继prototype之后又一个优秀的代码库(或者javascript框架).jQuery设计的宗旨是writeLess,Do M ...
- fiddler2抓包数据工具使用教程
一款免费且功能强大的数据包抓取软件.它通过代理的方式获取程序http通讯的数据,可以用其检测网页和服务器的交互情况,能够记录所有客户端和服务器间的http请求,支持监视.设置断点.甚至修改输入输出数据 ...
- 关于kingoroot这款软件
弃了饱受诟病的kingroot系列的软件,又出现了一款名为kingoroot的软件. 大约一年之前用过kingoroot的apk版,成功为我的手机root了,而且其行为也并不是那么流氓,所以当时对其很 ...
- Hello py
https://www.cnblogs.com/AdaminXie/p/8339863.html https://www.cnblogs.com/-clq/p/8340515.html https:/ ...
- [2]传奇3服务器源码分析一 LoginServer
留存 服务端下载地址: 点击这里
- SQLSetConnectAttr
SQLSetConnectAttr 函数定义: 用法类似于SQLSetEnvAttr,该函数是设置连接的各项属性用的 SQLRETURN SQLSetConnectAttr( SQLHDBC ...