PHP进程通信基础之信号量与共享内存通信

由于进程之间谁先执行并不确定,这取决于内核的进程调度算法,其中比较复杂。由此有可能多进程在相同的时间内同时访问共享内存,从而造成不可预料的错误。信号量这个名字起的令人莫名其妙,但是看其英文原意,就十分容易理解。

semaphore 英[ˈseməfɔ:(r)] vt. 发出信号,打旗语;

类似于指挥官的作用。

下面我们看下一个伪代码信号量的使用。

1、创建信号量唯一标识符

$ftok = ftok(__FILE__, 'a');

2、创建信号量资源ID

$sem_resouce_id = sem_get($ftok);

3、接受信号量

sem_acqure($sem_resource_id);

4、释放信号量

sem_release($sem_resource_id);

5、销毁信号量

sem_remove($sem_resource_id);

举个不文雅的例子,使我们容易理解这个信号量在生活中的用法。理解之后可以套用到我们编程领域。
一家公司只有一个卫生间。那么当有人上厕所的时候,都要获取一把锁(信号量),表示卫生间正在使用。代码如下:

sem_acqure($sem_resource_id);

那么员工上完厕所之后,就需要将锁打开,释放锁(信号量),表示现在可以允许别人使用。代码如下:

sem_release($sem_resource_id);

通过一个简单的锁,我们就能够知道当前的厕所(共享内存)是否可以使用。这个例子不雅观,但说明了问题。这篇博客也是有味道的博客,真是不容易。。。。以下是示例代码:

<?php
//创建共享内存区域
$shm_key = ftok(__FILE__, 'a');
$shm_id = shm_attach($shm_key, 1024, 0755);

//var_dump($shm_id);die(); resource(4) of type (sysvshm)
const SHARE_KEY = 1;
$child_list = [];

//加入信号量
$sem_id = ftok(__FILE__, 'b');
$signal = sem_get($sem_id);

//$signal resource(5) of type (sysvsem)

for ($i = 0; $i < 3; $i++) {
  $pid = pcntl_fork();
  if ($pid == -1) {
    exit("Fork fail!".PHP_EOL);
  } elseif ($pid == 0) {
    //获取信号量
    sem_acquire($signal);
    if (shm_has_var($shm_id,SHARE_KEY)) {
      $count = shm_get_var($shm_id, SHARE_KEY);
      $count++;
      //模拟业务处理
      $sec = rand(1, 3);
      sleep($sec);
      shm_put_var($shm_id, SHARE_KEY, $count);
    } else {
      $count = 0;
      $sec = rand(1, 3);
      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) > 0) {
  foreach ($child_list as $key => $pid) {
    $status = pcntl_waitpid($pid, $status);
    if ($status > 0 || $status == -1) {
      unset($child_list[$key]);
    }
  }
  sleep(1);
}

$count = shm_get_var($shm_id, SHARE_KEY);
echo " $count  ".PHP_EOL;

//销毁信号量
sem_remove($signal);

shm_remove($shm_id);
shm_detach($shm_id);
(0)

相关推荐

  • PHP下通过系统信号量加锁方式获取递增序列ID

    在网上搜了搜,有两个办法但都不太好:一个是简单的以进程ID+时间戳,或进程ID+随机数来产生近似的唯一ID,虽简单但对于追求"完美"的我不愿这样凑合,再说Apache2以后进程会维持相当长得时间,生成的ID发生碰撞的几率还是比较大的:第二个思路是通过Mysql的自增字段,这个就更不能考虑了,效率低不说,我的设计里压根就没数据库. 递增ID的获取是个过程: 1. 从全局某个存储中读取ID 2. 给ID加1 3. 将ID重新存入全局存储 在多进程或线程的程序中需要将上述3步作为单步的原子操

  • PHP进程通信基础之信号

    使用信号通信.可以使用kill -l 来查看当前系统的信号类型. 每个信号所代表的的详细含义,请查看我的这篇文章:http://www.jb51.net/article/106040.htm 使用信号的时候可以通过php --version 来查看当前PHP的版本.已决定使用哪种方式来进行进程间的信号通信. [root@roverliang ipc]# php --version PHP 5.6.24 (cli) (built: Aug 15 2016 19:14:02) Copyright (

  • PHP 信号管理知识整理汇总

    SIGQUIT    建立CORE文件终止进程,并且生成core文件 SIGILL     建立CORE文件       非法指令 SIGTRAP    建立CORE文件       跟踪自陷 SIGBUS     建立CORE文件       总线错误 SIGSEGV    建立CORE文件        段非法错误 SIGFPE     建立CORE文件       浮点异常 SIGIOT     建立CORE文件        执行I/O自陷 SIGSTOP    停止进程     非终端

  • PHP信号量基本用法实例详解

    本文实例讲述了PHP信号量基本用法.分享给大家供大家参考,具体如下: 一些理论基础: 信号量:又称为信号灯.旗语 用来解决进程(线程同步的问题),类似于一把锁,访问前获取锁(获取不到则等待),访问后释放锁. 临界资源:每次仅允许一个进程访问的资源. 临界区:每个进程中访问临界资源的那段代码叫临界区 进程互斥:两个或以上的进程不能同时进入关于同一组共享变量的临界区域,即一个进程正在访问临界资源,另一个进程要想访问必须等待. 进程同步主要研究如何确定数个进程之间的执行顺序和避免数据竞争的问题 即,如

  • PHP进程通信基础之信号量与共享内存通信

    由于进程之间谁先执行并不确定,这取决于内核的进程调度算法,其中比较复杂.由此有可能多进程在相同的时间内同时访问共享内存,从而造成不可预料的错误.信号量这个名字起的令人莫名其妙,但是看其英文原意,就十分容易理解. semaphore 英[ˈseməfɔ:(r)] vt. 发出信号,打旗语; 类似于指挥官的作用. 下面我们看下一个伪代码信号量的使用. 1.创建信号量唯一标识符 $ftok = ftok(__FILE__, 'a'); 2.创建信号量资源ID $sem_resouce_id = sem

  • php进程(线程)通信基础之System V共享内存简单实例分析

    本文实例讲述了php进程(线程)通信基础之System V共享内存.分享给大家供大家参考,具体如下: PHP默认情况没有开启功能,要支持该功能在编译PHP的时候要加入下面几个选项  System V消息,--enable-sysvmsg   System V信号量支持,--enable-sysvsem  System V共享内存支持,--enable-sysvshm PHP还挺shmop共享内存,在编译的时候开启 --enable-shmop System V共享内存的相关函数: 1: 创建信号

  • PHP共享内存使用与信号控制实例分析

    本文实例讲述了PHP共享内存使用与信号控制.分享给大家供大家参考,具体如下: 共享内存 共享内存的使用主要是为了能够在同一台机器不同的进程中共享一些数据,比如在多个 php-fpm 进程中共享当前进程的使用情况.这种通信也称为进程间通信(Inter-Process Communication),简称 IPC. PHP 内置的 shmop 扩展 (Shared Memory Operations) 提供了一系列共享内存操作的函数(可能是用的人不多吧,这一块儿的文档还没有中文翻译).在 Linux

  • node 利用进程通信实现Cluster共享内存

    Node.js的标准API没有提供进程共享内存,然而通过IPC接口的send方法和对message事件的监听,就可以实现一个多进程之间的协同机制,通过通信来操作共享内存. ##IPC的基本用法: // worker进程 发送消息 process.send('读取共享内存'); // master进程 接收消息 -> 处理 -> 发送回信 cluster.on('online', function (worker) { // 有worker进程建立,即开始监听message事件 worker.o

  • Linux共享内存实现机制的详解

    Linux共享内存实现机制的详解 内存共享: 两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反之亦然.由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 效率: 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据[1]: 一次从输入文件到

  • 详解Linux进程间通信——使用共享内存

    一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 特别提醒:共享内存并未提供同步机制,也就是说,在第一个进程结束

  • Linux之进程间通信(共享内存【mmap实现+系统V】)

    目录 共享内存 mmap()及其相关的系统调用 mmap() munmap() 共享内存的使用 命令管理共享内存 总结 共享内存 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式,两个不同的进程A.B共享内存的意思就是:同一块物理内存被映射到进程A.B各自的进程地址空间,进程A可以同时看到进程B对共享内存中数据的更新,反之亦然. 由于个多个进程共享同一块内存区域,必然需要某种同步机制.互斥锁和信号量都可以. 好处: 效率高,进程可以直接读写内存,而不需要复制任何数据,而管道.消息队列

  • nginx中共享内存的使用详解

    在nginx的进程模型下,类似流量统计.流量控制.数据共享.等需要多个工作进程共同配合完成任务,共享内存是一个重要的进程通讯的方案.本文介绍在nginx的代码中与共享内存相关的功能,包括ngx_shmem与ngx_slab的使用与注意事项,但不包括ngx_slab中实现的内存管理算法. ngx_shmem的使用 ngx_shmem.c/h文件只是对mmap()/munmap()系统调用或者shmget()/shmdt()的一个很简单的封装.实现了ngx风格的基础库,可以申请和释放一段连续的共享内

  • 解决Linux system v 共享内存问题

    system v 共享内存 #include <sys/types.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); 建立:进程与共享内存的关联关系 key_t key:16进制的非0数字. 一般有两种方式设置它. 第一种:调用fotk函数 第二章:直接使用IPC_PRIVATE size:共享内存的大小 shmflg: IPC_CREAT IPC_EXCL 用户,组用户,其他用户对这片内

  • 单台服务器的PHP进程之间实现共享内存的方法

    开发人员要想使php进程实现共享内存的读写,首先就要支持IPC函数,即php编译安装时指定:--enable-shmop  与--enable-sysvsem 两个选项. IPC (Inter-process communication) 是一个Unix标准机制,它提供了使得在同一台主机不同进程之间可以互相的方法.基本的IPC处理机制有3种:它们分别是共享内存.信号量和消息队列.本文中我们主要讨论共享内存和信号量的使用. 在不同的处理进程之间使用共享内存是一个实现不同进程之间相互的好方法.如果你

随机推荐