当前位置:首页 > PHP教程 > php应用 > 列表

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

发布:smiling 来源: PHP粉丝网  添加日期:2018-08-02 15:50:02 浏览: 评论:0 

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

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);

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

 
  1. //创建共享内存区域 
  2. $shm_key = ftok(__FILE__,'a'); 
  3. $shm_id = shm_attach($shm_key, 1024, 0755); 
  4.   
  5. //var_dump($shm_id);die(); resource(4) oftype(sysvshm) 
  6. const SHARE_KEY = 1; 
  7. $child_list = []; 
  8.   
  9. //加入信号量 
  10. $sem_id = ftok(__FILE__,'b'); 
  11. $signal = sem_get($sem_id); 
  12.   
  13. //$signal resource(5) oftype(sysvsem) 
  14.   
  15.   
  16. for($i = 0; $i < 3; $i++) { 
  17.   $pid = pcntl_fork(); 
  18.   if($pid == -1) { 
  19.     exit("Fork fail!".PHP_EOL); 
  20.   } elseif ($pid == 0) { 
  21.     //获取信号量 
  22.     sem_acquire($signal); 
  23.     if(shm_has_var($shm_id,SHARE_KEY)) { 
  24.       $count = shm_get_var($shm_id, SHARE_KEY); 
  25.       $count++; 
  26.       //模拟业务处理 
  27.       $sec = rand(1, 3); 
  28.       sleep($sec); 
  29.       shm_put_var($shm_id, SHARE_KEY, $count); 
  30.     }else
  31.       $count = 0; 
  32.       $sec = rand(1, 3); 
  33.       sleep($sec); 
  34.       shm_put_var($shm_id, SHARE_KEY, $count); 
  35.     } 
  36.   
  37.     echo"child process: ".getmypid()." is writing! now count is: $count ".PHP_EOL; 
  38.   
  39.     //释放信号量 
  40.     sem_release($signal); 
  41.     exit("child process".getmypid()."end".PHP_EOL); 
  42.   }else
  43.     $child_list[] = $pid
  44.   } 
  45.   
  46. while(count($child_list) > 0) { 
  47.   <a href="/tags.php/foreach/" target="_blank">foreach</a> ($child_list as $key => $pid) { 
  48.     $status = pcntl_waitpid($pid$status); 
  49.     if($status > 0 || $status == -1) { 
  50.       unset($child_list[$key]); 
  51.     } 
  52.   } 
  53.   sleep(1); 
  54.   
  55. $count = shm_get_var($shm_id, SHARE_KEY); 
  56. echo" $count  ".PHP_EOL; 
  57. //phpfensi.com 
  58. //销毁信号量 
  59. sem_remove($signal); 
  60.   
  61. shm_remove($shm_id); 
  62. shm_detach($shm_id); 

Tags: 信号量 进程 内存

分享到: