在单独的一个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的使用方法,那么就必须要了解一下信号量是什么,以及信号量使用的代码案例的更多相关文章

  1. linux实现共享内存同步的四种方法

    https://blog.csdn.net/sunxiaopengsun/article/details/79869115 本文主要对实现共享内存同步的四种方法进行了介绍. 共享内存是一种最为高效的进 ...

  2. php 共享内存学习(shmop函数)

    问题:希望可以在进程间共享变量,为共享数据提供快速访问 解决方案:除了可以使用APC模块,还可以用shmop或System V共享内存 //创建键 //将一个可访问的文件路径名转换为一个可供 shmo ...

  3. 创建共享内存函数CreateFileMapping()详解

    测试创建和打开文件映射的时候老是得到"句柄无效"的错误, 仔细看了MSDN以后才发觉是函数认识不透, 这里把相关的解释翻译出来 HANDLE CreateFileMapping( ...

  4. C++ 共享内存 函数封装

    #pragma once #include <string> #include <wtypes.h> #include <map> using namespace ...

  5. 给PHP开启shmop扩展实现共享内存

    在项目开发中,想要实现PHP多个进程之间共享数据的功能,让客户端连接能够共享一个状态,需要开启共享内存函数shmop.如果预期考虑会遇到这方面需求,那么最好在编译PHP的时候添加--with-shmo ...

  6. Linux POSIX共享内存方法&ipcs &struct shmid_ds

    内容是主进程创建子进程计算斐波那契数列. 其中计算到第几项是有主进程命令行输入. 共享内存段,并且查看了一些信息. 参考操作系统概念第七版 3.10,3.11 关于LINUX C库函数 中的 fpri ...

  7. c#读写共享内存操作函数封装

    原文 c#读写共享内存操作函数封装 c#共享内存操作相对c++共享内存操作来说原理是一样,但是c#会显得有点复杂. 现把昨天封装的读写共享内存封装的函数记录下来,一方面希望给需要这块的有点帮助,另一方 ...

  8. System V 共享内存 和 系列函数

    跟消息队列一样,共享内存也有自己的数据结构,如下: struct shmid_ds { struct ipc_perm shm_perm;    /* Ownership and permission ...

  9. PHP共享内存详解

    前言 在PHP中有这么一族函数,他们是对UNIX的V IPC函数族的包装. 它们很少被人们用到,但是它们却很强大.巧妙的运用它们,可以让你事倍功半. 它们包括: 信号量(Semaphores) 共享内 ...

随机推荐

  1. huawei

    线程堆栈(Thread Stack)和托管堆(Managed Heap) 每个正在运行的程序都对应着一个进程 (process),在一个进程内部,可以有一个或多个线程(thread),每个线程都拥有一 ...

  2. 合理利用配置不同的机器资源做redis cluster的server

    Redis cluster可以使用不同配置的机器学习因为我们可以手动调整不同的机器所承担的slot的个数,这样内存小CPU相对少的机器应该承担更少的slots

  3. 3-Python3 环境搭建

  4. JDB调试

  5. jmeter BeanShell断言(一)

    原文地址https://blog.csdn.net/lijing742180/article/details/81157947 原文地址https://blog.csdn.net/zailushang ...

  6. cocos2dx (关于斗地主人物偏移位置)

    就是说不管是谁登陆游戏,你的人物信息资料始终在平板电脑的屏幕正下方(位置坐标需要自己设定,我设置定的是0号位() char LandLordsScene::getUIPosition(char pos ...

  7. linux 小笔记

    //强杀pid2306的进程 kill -9 2306 //查看80端口占用情况 lsof -i :80 //杀死mysql的所有进程 sudo killall mysqld //关闭占用80端口的所 ...

  8. 监控Tomcat

    监控Tomcat 无论是使用Zabbix.还是jconsole等其他工具,当需要监控Tomcat时,需对Tomcat进行jmx配置.此处以Linux系统为例,配置Tomcat. 注意: 下文中出现的: ...

  9. 018-AJAX异步请求XMLHttpRequest

    创建XMLHttpRequest对象 一.先来创建XMLHttpRequest对象在IE.Firefox.safari和Opera中创建该对象的JavaScript代码为: var xhr = new ...

  10. 在运行create_list.sh时候报错:AttributeError: 'module' object has no attribute 'LabelMap'

    Traceback (most recent call last):File "/opt/xuben-project/caffe/data/VOC0712/../../scripts/cre ...