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


Posted in PHP onFebruary 19, 2017

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

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);
PHP 相关文章推荐
phpBB BBcode处理的漏洞
Oct 09 PHP
第三节--定义一个类
Nov 16 PHP
dedecms模板标签代码官方参考
Mar 17 PHP
PHP strtotime函数详解
Dec 18 PHP
zend api扩展的php对象的autoload工具
Apr 18 PHP
PHP gbk环境下json_dencode传送来的汉字
Nov 13 PHP
Laravel 5框架学习之用户认证
Apr 09 PHP
php利用事务处理转账问题
Apr 22 PHP
PHP文件缓存类实现代码
Oct 26 PHP
Yii2实现ajax上传图片插件用法
Apr 28 PHP
PHP实现的自定义数组排序函数与排序类示例
Nov 18 PHP
PHP共享内存使用与信号控制实例分析
May 09 PHP
PHP进程通信基础之信号
Feb 19 #PHP
PHP 信号管理知识整理汇总
Feb 19 #PHP
php 三大特点:封装,继承,多态
Feb 19 #PHP
PHP实现大数(浮点数)取余的方法
Feb 18 #PHP
Zend Framework基于Command命令行建立ZF项目的方法
Feb 18 #PHP
完美解决php 导出excle的.csv格式的数据时乱码问题
Feb 18 #PHP
Zend Framework数据库操作技巧总结
Feb 18 #PHP
You might like
PHP编程中的常见漏洞和代码实例
2014/08/06 PHP
php生成二维码
2015/08/10 PHP
strpos() 函数判断字符串中是否包含某字符串的方法
2019/01/16 PHP
Laravel 实现数据软删除功能
2019/08/21 PHP
PHP底层运行机制与工作原理详解
2020/07/31 PHP
javascript html 静态页面传参数
2009/04/10 Javascript
jquery插件如何使用 jQuery操作Cookie插件使用介绍
2012/12/15 Javascript
jQuery插件开发基础简单介绍
2013/01/07 Javascript
js计算精度问题小结
2013/04/22 Javascript
使用纯javascript实现经典扫雷游戏
2015/04/23 Javascript
元素绑定click点击事件方法
2015/06/08 Javascript
浅谈JavaScript中变量和函数声明的提升
2016/08/09 Javascript
BootStrap中的表单大全
2016/09/07 Javascript
vue 解决循环引用组件报错的问题
2018/09/06 Javascript
js中怎么判断两个字符串相等的实例
2019/01/17 Javascript
支付宝小程序实现省市区三级联动
2020/06/21 Javascript
基于vue中的scoped坑点解说
2020/09/04 Javascript
[44:22]完美世界DOTA2联赛循环赛 FTD vs PXG BO2第一场 11.01
2020/11/02 DOTA
python将ip地址转换成整数的方法
2015/03/17 Python
Python网络爬虫出现乱码问题的解决方法
2017/01/05 Python
Python实现简单的语音识别系统
2017/12/13 Python
Python3处理HTTP请求的实例
2018/05/10 Python
详解Python requests 超时和重试的方法
2018/12/18 Python
Python中的Socket 与 ScoketServer 通信及遇到问题解决方法
2019/04/01 Python
Python字符串对象实现原理详解
2019/07/01 Python
提供世界各地便宜的机票:Sky-tours
2016/07/21 全球购物
Paul Smith英国官网:英国国宝级时装品牌
2019/03/21 全球购物
关键字final的用法
2013/10/02 面试题
空字符串(“”)和null的区别
2012/11/13 面试题
竞聘上岗演讲
2014/05/19 职场文书
2014高考励志标语
2014/06/05 职场文书
理发店策划方案
2014/06/05 职场文书
招标保密承诺书
2015/01/20 职场文书
助学感谢信范文
2015/01/21 职场文书
大学生实习证明
2015/06/16 职场文书
小学四年级作文之最感动的一件事
2019/11/01 职场文书