PHP下操作Linux消息队列完成进程间通信的方法


Posted in PHP onJuly 24, 2010

关于Linux系统进程通信的概念及实现可查看:http://www.ibm.com/developerworks/cn/linux/l-ipc/

关于Linux系统消息队列的概念及实现可查看:http://www.ibm.com/developerworks/cn/linux/l-ipc/part4/

PHP的sysvmsg模块是对Linux系统支持的System V IPC中的System V消息队列函数族的封装。我们需要利用sysvmsg模块提供的函数来进进程间通信。先来看一段示例代码_1:

<?php 
$message_queue_key = ftok(__FILE__, 'a'); 
$message_queue = msg_get_queue($message_queue_key, 0666); 
var_dump($message_queue); 
$message_queue_status = msg_stat_queue($message_queue); 
print_r($message_queue_status); 
//向消息队列中写 
msg_send($message_queue, 1, "Hello,World!"); 
$message_queue_status = msg_stat_queue($message_queue); 
print_r($message_queue_status); 
//从消息队列中读 
msg_receive($message_queue, 0, $message_type, 1024, $message, true, MSG_IPC_NOWAIT); 
print_r($message."\r\n"); 
msg_remove_queue($message_queue); 
?>

这段代码的运行结果如下:
resource(4) of type (sysvmsg queue) 
Array 
( 
[msg_perm.uid] => 1000 
[msg_perm.gid] => 1000 
[msg_perm.mode] => 438 
[msg_stime] => 0 
[msg_rtime] => 0 
[msg_ctime] => 1279849495 
[msg_qnum] => 0 
[msg_qbytes] => 16384 
[msg_lspid] => 0 
[msg_lrpid] => 0 
) 
Array 
( 
[msg_perm.uid] => 1000 
[msg_perm.gid] => 1000 
[msg_perm.mode] => 438 
[msg_stime] => 1279849495 
[msg_rtime] => 0 
[msg_ctime] => 1279849495 
[msg_qnum] => 1 
[msg_qbytes] => 16384 
[msg_lspid] => 2184 
[msg_lrpid] => 0 
) 
Hello,World!

可以看到已成功从消息队列中读取“Hello,World!”字符串

下面列举一下示例代码中的主要函数:

ftok ( string $pathname , string $proj ) 
手册上给出的解释是:Convert a pathname and a project identifier to a System V IPC key。这个函数返回的键值唯一对应linux系统中一个消息队列。在获得消息队列的引用之前都需要调用这个函数。 
msg_get_queue ( int $key [, int $perms ] ) 
msg_get_queue()会根据传入的键值返回一个消息队列的引用。如果linux系统中没有消息队列与键值对应,msg_get_queue()将会创建一个新的消息队列。函数的第二个参数需要传入一个int值,作为新创建的消息队列的权限值,默认为0666。这个权限值与linux命令chmod中使用的数值是同一个意思,因为在linux系统中一切皆是文件。 
msg_send ( resource $queue , int $msgtype , mixed $message [, bool $serialize [, bool $blocking [, int &$errorcode ]]] ) 
顾名思义,该函数用来向消息队列中写数据。 
msg_stat_queue ( resource $queue ) 
这个函数会返回消息队列的元数据。消息队列元数据中的信息很完整,包括了消息队列中待读取的消息数、最后读写队列的进程ID等。示例代码在第8行调用该函数返回的数组中队列中待读取的消息数msg_qnum值为0。 
msg_receive ( resource $queue , int $desiredmsgtype , int &$msgtype , int $maxsize , mixed &$message [, bool $unserialize [, int $flags [, int &$errorcode ]]] ) 
msg_receive用于读取消息队列中的数据。 
msg_remove_queue ( resource $queue ) 
msg_remove_queue用于销毁一个队列。

示例代码_1只是展示了PHP操作消息队列函数的应用。下面的代码具体描述了进程间通信的场景
<?php 
$message_queue_key = ftok(__FILE__, 'a'); 
$message_queue = msg_get_queue($message_queue_key, 0666); 
$pids = array(); 
for ($i = 0; $i < 5; $i++) { 
//创建子进程 
$pids[$i] = pcntl_fork(); 
if ($pids[$i]) { 
echo "No.$i child process was created, the pid is $pids[$i]\r\n"; 
} elseif ($pids[$i] == 0) { 
$pid = posix_getpid(); 
echo "process.$pid is writing now\r\n"; 
msg_send($message_queue, 1, "this is process.$pid's data\r\n"); 
posix_kill($pid, SIGTERM); 
} 
} 
do { 
msg_receive($message_queue, 0, $message_type, 1024, $message, true, MSG_IPC_NOWAIT); 
echo $message; 
//需要判断队列是否为空,如果为空就退出 
//break; 
} while(true) 
?>

运行结果为:
No.0 child process was created, the pid is 5249 
No.1 child process was created, the pid is 5250 
No.2 child process was created, the pid is 5251 
No.3 child process was created, the pid is 5252 
No.4 child process was created, the pid is 5253 
process.5251 is writing now 
this is process.5251's data 
process.5253 is writing now 
process.5252 is writing now 
process.5250 is writing now 
this is process.5253's data 
this is process.5252's data 
this is process.5250's data 
process.5249 is writing now 
this is process.5249's data

这段程序每次的运行结果都会不同,这正说明了多进程的异步性。从结果也能看出消息队列FIFO特性。
以上便是我研究的一点心得。接下来将会继续研究PHP利用信号、socket等进行进程间通信的方法。
PHP 相关文章推荐
第六节--访问属性和方法
Nov 16 PHP
PHP 编程请选择正确的文本编辑软件
Dec 21 PHP
php 网页播放器用来播放在线视频的代码(自动判断并选择视频文件类型)
Jun 03 PHP
php 短链接算法收集与分析
Dec 30 PHP
PHP中的Streams详细介绍
Nov 12 PHP
php+mysqli使用面向对象方式更新数据库实例
Jan 29 PHP
PHP使用ffmpeg给视频增加字幕显示的方法
Mar 12 PHP
PHP的Socket通信之UDP通信实例
Jul 02 PHP
php自动加载方式集合
Apr 04 PHP
php cookie用户登录的详解及实例代码
Jan 03 PHP
利用phpexcel对数据库数据的导入excel(excel筛选)、导出excel
Apr 27 PHP
PHP substr()函数参数解释及用法讲解
Nov 23 PHP
php抓取页面与代码解析 推荐
Jul 23 #PHP
由php的call_user_func传reference引发的思考
Jul 23 #PHP
Google Voice 短信发送接口PHP开源版(2010.5更新)
Jul 22 #PHP
PHP 飞信好友免费短信API接口开源版
Jul 22 #PHP
PHP计划任务之关闭浏览器后仍然继续执行的函数
Jul 22 #PHP
PHP垃圾回收机制简单说明
Jul 22 #PHP
PHP多线程抓取网页实现代码
Jul 22 #PHP
You might like
php判断字符以及字符串的包含方法属性
2008/08/30 PHP
php简单提示框alert封装函数
2010/08/08 PHP
详解php的socket通信
2015/08/11 PHP
基于jQuery的烟花效果(运动相关)点击屏幕出烟花
2012/06/14 Javascript
JS小功能(button选择颜色)简单实例
2013/11/29 Javascript
angularjs 处理多个异步请求方法汇总
2015/01/06 Javascript
JavaScript运算符小结
2015/06/03 Javascript
JavaScript中的原型prototype属性使用详解
2015/06/05 Javascript
jQuery Easyui学习之datagrid 动态添加、移除editor
2016/01/27 Javascript
arcgis for js 修改infowindow样式的方法
2016/11/02 Javascript
BootstrapTable请求数据时设置超时(timeout)的方法
2017/01/22 Javascript
NodeJS测试框架mocha入门教程
2017/03/28 NodeJs
基于jQuery实现定位导航位置效果
2017/11/15 jQuery
零基础之Node.js搭建API服务器的详解
2019/03/08 Javascript
[01:23:35]Ti4主赛事胜者组 DK vs EG 1
2014/07/19 DOTA
jupyter安装小结
2016/03/13 Python
Python学习小技巧之列表项的推导式与过滤操作
2017/05/20 Python
对python抓取需要登录网站数据的方法详解
2018/05/21 Python
Django csrf 两种方法设置form的实例
2019/02/03 Python
利用python计算windows全盘文件md5值的脚本
2019/07/27 Python
对YOLOv3模型调用时候的python接口详解
2019/08/26 Python
python实现加密的方式总结
2020/01/19 Python
推荐8款常用的Python GUI图形界面开发框架
2020/02/23 Python
使用opencv识别图像红色区域,并输出红色区域中心点坐标
2020/06/02 Python
python绘制雷达图实例讲解
2021/01/03 Python
英国办公家具网站:Furniture At Work
2019/10/07 全球购物
Scotch Porter官方网站:男士美容产品
2020/08/31 全球购物
我能否用void** 指针作为参数, 使函数按引用接受一般指针
2013/02/16 面试题
几个判断型的面试题
2012/07/03 面试题
数据管理员的自我评价分享
2013/11/15 职场文书
小学雷锋月活动总结
2014/07/03 职场文书
写字楼租赁意向书
2014/07/30 职场文书
2014年内部审计工作总结
2014/12/09 职场文书
大学教师个人总结
2015/02/10 职场文书
商场圣诞节活动总结
2015/05/06 职场文书
与死神共舞观后感
2015/06/15 职场文书