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 相关文章推荐
多重?l件?合查?(一)
Oct 09 PHP
超强分页类2.0发布,支持自定义风格,默认4种显示模式
Jan 02 PHP
php 大数据量及海量数据处理算法总结
May 07 PHP
PHP使用glob函数遍历目录或文件夹的方法
Dec 16 PHP
PHP浮点数精度问题汇总
May 13 PHP
php中foreach结合curl实现多线程的方法分析
Sep 22 PHP
在Thinkphp中使用ajax实现无刷新分页的方法
Oct 25 PHP
php实现等比例不失真缩放上传图片的方法
Nov 14 PHP
php中html_entity_decode实现HTML实体转义
Jun 13 PHP
详解php用static方法的原因
Sep 12 PHP
PHP7内核CGI与FastCGI详解
Apr 14 PHP
yii2.0框架多模型操作示例【添加/修改/删除】
Apr 13 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
Laravel模板引擎Blade中section的一些标签的区别介绍
2015/02/10 PHP
利用PHP fsockopen 模拟POST/GET传送数据的方法
2015/09/22 PHP
php性能分析之php-fpm慢执行日志slow log用法浅析
2016/10/17 PHP
基于jquery的图片幻灯展示源码
2012/07/15 Javascript
使用闭包对setTimeout进行简单封装避免出错
2013/07/10 Javascript
JS动态增加删除UL节点LI及相关内容示例
2014/05/21 Javascript
浅谈JS闭包中的循环绑定处理程序
2014/11/09 Javascript
javascript实现tab切换的两个实例
2015/11/05 Javascript
谈谈PHP中相对路径的问题与绝对路径的使用
2016/08/16 Javascript
JS访问DOM节点方法详解
2016/11/29 Javascript
React-router中结合webpack实现按需加载实例
2017/05/25 Javascript
Vue中对iframe实现keep alive无刷新的方法
2019/07/23 Javascript
Vue项目结合Vue-layer实现弹框式编辑功能(实例代码)
2020/03/11 Javascript
解决Vue + Echarts 使用markLine标线(precision精度问题)
2020/07/20 Javascript
解决在Vue中使用axios POST请求变成OPTIONS的问题
2020/08/14 Javascript
nginx配置域名后的二级目录访问不同项目的配置操作
2020/11/06 Javascript
nestjs返回给前端数据格式的封装实现
2021/02/22 Javascript
Python批量创建迅雷任务及创建多个文件
2016/02/13 Python
python的文件操作方法汇总
2017/11/10 Python
详解Python的hasattr() getattr() setattr() 函数使用方法
2018/07/09 Python
python中map的基本用法示例
2018/09/10 Python
利用python修改json文件的value方法
2018/12/31 Python
Python Excel处理库openpyxl使用详解
2019/05/09 Python
python实现井字棋小游戏
2020/03/04 Python
Python多个装饰器的调用顺序实例解析
2020/05/22 Python
Html5实现单张、多张图片上传功能
2019/04/28 HTML / CSS
Html5新标签解释及用法
2012/02/17 HTML / CSS
如何写出好的Java代码
2014/04/25 面试题
Java基础类库面试题
2013/09/04 面试题
金融专业推荐信
2013/11/14 职场文书
青年教师培训方案
2014/02/06 职场文书
ktv筹备计划书
2014/05/03 职场文书
学校课外活动总结
2014/05/08 职场文书
南京导游词
2015/02/03 职场文书
MySQL数据库压缩版本安装与配置详细教程
2021/05/21 MySQL
vue使用echarts实现折线图
2022/03/21 Vue.js