作为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) 共享内 ...
随机推荐
- dfs模版
dfs #include <stdio.h> #include <string.h> char Map[16][16]; int mv[16][16]; //mv[i][j] ...
- 冒泡排序(Python实现)
目录 1. while版本--冒泡排序 2. for版本--冒泡排序 3. 测试用例 4. 算法时间复杂度分析 1. while版本--冒泡排序 def bubble_sort_while(a_lis ...
- bat/cmd将命令执行的结果赋值给变量
比如我想把git代码的commitid获取以后加到文件夹上来标记文件夹中的包是哪个git 节点构建得到的. git 命令是git rev-parse --short HEAD 再linux系统下,只需 ...
- [LeetCode] Backtracking Template for (Subsets, Permutations, and Combination Sum)
根据issac3 用Java总结了backtracking template, 我用他的方法改成了Python. 以下为template. def backtrack(ans, temp, nums, ...
- iOS 设计模式-Block实现代理的逻辑
在A页面,点击跳转到B页面,B页面操作完,回到A页面,并刷新A页面的内容.典型的例子,就是在一个列表里,点击新增,跳到新增页面,新增完,把数据传回给列表页,并刷新列表页里的内容. 这个,我平时一般是通 ...
- C++ 类定义
C++ 类定义 定义一个类,本质上是定义一个数据类型的蓝图.这实际上并没有定义任何数据,但它定义了类的名称意味着什么,也就是说,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作. 类定义是 ...
- vue中使用ckeditor
1.第一步首先去ckeditor官网去下载editor文件,这里以ckeditor4为例 首先在index.html里引入js代码 <script type="text/javascr ...
- python number
一.number类型转换 int(x [,base ]) 将x转换为一个整数 long(x [,base ]) 将x转换为一个长整数 float(x ) 将x转换到一个浮点数 complex(real ...
- Bootstrap-全局CSS样式-图片样式
Bootstrap第二部分:全局CSS样式-图片样式.img-rounded 圆角图片.img-circle 圆形图片.img-thumbnail 缩略图片.img-responsive响应 ...
- 关于c语言中的program_invocation_short_name
错误源自用g++的交叉编译工具链编译eudev.经过一番查找,发现在 errno.h 这个头文件中有 program_invocation_short_name 的 extern 定义. 经过查看 e ...