在单独的一个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. vue watch 监听element upload组件上传成功返回的url列表

    因为 on-success 上传成功返回的是一个异步的结果....如果父组件需要这个结果的话 必须用watch 监听 然后里面建立一个 save()方法 save方法里面再调用接口 传需要的上传之后的 ...

  2. [Java in NetBeans] Lesson 11. While Loops

    这个课程的参考视频和图片来自youtube. 主要学到的知识点有:(the same use in C/C++) 1. while loop while(i < max){} will keep ...

  3. linux shell脚本检测硬盘磁盘空间 邮件报警

    使用 http://www.weiruoyu.cn/?p=368 shell脚本监控硬盘空间剩余空间 邮件报警 1.先观察一下磁盘,和如何使用脚本 [root@localhost ~]# df -h ...

  4. 8.C#友元程序集----可访问性相关

    在一个团队或者公司中,一个人开发出来的程序集中的类的可见性有public,private和internal, public:对所有程序集可见,就是说如果拿到程序集.DLL文件,那么类就被公开了. pr ...

  5. unittest多线程生成报告-----BeautifulReport

    原文地址https://www.cnblogs.com/yoyoketang/p/8404204.html 前言 selenium多线程跑用例,这个前面一篇已经解决了,如何生成一个测试报告这个是难点, ...

  6. JAVA编程思想学习笔记4-chap10-12-斗之气4段

    1.内部类:Iterator 2..this生成对外部类的引用 3..new:通过外部类对象创建内部类对象 package com.chengjie; public class TestInnerCl ...

  7. ASP.Net Core 2.2 MVC入门到基本使用系列 (二)(转)

    本教程会对基本的.Net Core 进行一个大概的且不会太深入的讲解, 在您看完本系列之后, 能基本甚至熟练的使用.Net Core进行Web开发, 感受到.Net Core的魅力. 本教程知识点大体 ...

  8. 函数式编程语言(functional language)

    内容根据百度词条整理! 转载请声明来源:https://baike.baidu.com/item/%E5%87%BD%E6%95%B0%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8 ...

  9. innerText 与 innerHtml的区别

    j基本语法类似: innerHTML/innerText ->给除了表单元素的标签赋值内容 document.getElementById("div1").innerHTML ...

  10. Vue系列之 => 动画

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...