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 相关文章推荐
php的计数器程序
Oct 09 PHP
php垃圾代码优化操作代码
Aug 05 PHP
php实现分页工具类分享
Jan 09 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(五)
Jun 23 PHP
PHP中使用localhost连接Mysql不成功的解决方法
Aug 20 PHP
PHP实现视频文件上传完整实例
Aug 28 PHP
php中http与https跨域共享session的解决方法
Dec 20 PHP
php实现比较两个文件夹异同的方法
Jun 18 PHP
php根据年月获取当月天数及日期数组的方法
Nov 30 PHP
laravel5实现微信第三方登录功能
Dec 06 PHP
PHP 多进程与信号中断实现多任务常驻内存管理实例方法
Oct 04 PHP
PHP 实现base64编码文件上传出现问题详解
Sep 01 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跳出循环的方法以及continue、break、exit的区别介绍
2013/07/01 PHP
php通过strpos查找字符串出现位置的方法
2015/03/17 PHP
ThinkPHP表单数据智能写入create方法实例分析
2015/09/27 PHP
PHP图片水印类的封装
2017/07/06 PHP
PHP设计模式之注册树模式分析
2018/01/26 PHP
给Javascript数组插入一条记录的代码
2007/08/30 Javascript
一个简单的js鼠标划过切换效果
2010/06/30 Javascript
javascript:文字不间断向左移动的实例代码
2013/08/08 Javascript
JavaScript实现twitter puddles算法实例
2014/12/06 Javascript
javascript批量修改文件编码格式的方法
2015/01/27 Javascript
让图片跳跃起来  javascript图片轮播特效
2016/02/16 Javascript
完美解决js传递参数中加号和&amp;号自动改变的方法
2016/10/11 Javascript
js初始化验证实例详解
2016/11/26 Javascript
JavaScript模板引擎Template.js使用详解
2016/12/15 Javascript
Node.js利用Net模块实现多人命令行聊天室的方法
2016/12/23 Javascript
jQuery zTree树插件简单使用教程
2017/01/10 Javascript
vue2.0实现倒计时的插件(时间戳 刷新 跳转 都不影响)
2017/03/30 Javascript
浅谈Vue路由快照实现思路及其问题
2018/06/07 Javascript
JS实现获取毫秒值及转换成年月日时分秒的方法
2018/08/15 Javascript
vue-cli 3.x 配置Axios(proxyTable)跨域代理方法
2018/09/19 Javascript
原生JS实现轮播图效果
2018/10/12 Javascript
iview tabs 顶部导航栏和模块切换栏的示例代码
2019/03/04 Javascript
JS实现在线ps功能详解
2019/07/31 Javascript
vue 弹出遮罩层样式实例
2020/07/22 Javascript
Python中的数学运算操作符使用进阶
2016/06/20 Python
Pycharm学习教程(2) 代码风格
2017/05/02 Python
Python多重继承的方法解析执行顺序实例分析
2018/05/26 Python
Python3使用turtle绘制超立方体图形示例
2018/06/19 Python
Python中zipfile压缩文件模块的基本使用教程
2020/06/14 Python
Python Charles抓包配置实现流程图解
2020/09/29 Python
社保转移委托书范本
2014/10/08 职场文书
2014年文员工作总结
2014/11/18 职场文书
JS实现简单控制视频播放倍速的实例代码
2021/04/18 Javascript
Node.js实现爬取网站图片的示例代码
2022/04/04 NodeJs
深入理解 Golang 的字符串
2022/05/04 Golang
JS class语法糖的深入剖析
2022/07/07 Javascript