利用PHP操作Linux消息队列完成进程间通信
admin
- 3 minutes read - 507 words当我们开发的系统需要使用多进程方式运行时,进程间通信便成了至关重要的环节。消息队列(message queue)是Linux系统进程间通信的一种方式。
关于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:
01``<?php
02
03``$message_queue_key = ftok ( __FILE__ , 'a' );
04
05``$message_queue = msg_get_queue( $message_queue_key , 0666);
06``var_dump( $message_queue );
07
08``$message_queue_status = msg_stat_queue( $message_queue );
09``print_r( $message_queue_status );
10
11``//向消息队列中写
12``msg_send( $message_queue , 1, "Hello,World!" );
13
14``$message_queue_status = msg_stat_queue( $message_queue );
15``print_r( $message_queue_status );
16
17``//从消息队列中读
18``msg_receive( $message_queue , 0, $message_type , 1024, $message , true, MSG_IPC_NOWAIT);
19``print_r( $message . "rn" );
20
21``msg_remove_queue( $message_queue );
22
23``?>
这段代码的运行结果如下:
01``resource(4) of type (sysvmsg queue)
02``Array
03``(
04`` ``[msg_perm.uid] => 1000
05`` ``[msg_perm.gid] => 1000
06`` ``[msg_perm.mode] => 438
07`` ``[msg_stime] => 0
08`` ``[msg_rtime] => 0
09`` ``[msg_ctime] => 1279849495
10`` ``[msg_qnum] => 0
11`` ``[msg_qbytes] => 16384
12`` ``[msg_lspid] => 0
13`` ``[msg_lrpid] => 0
14``)
15``Array
16``(
17`` ``[msg_perm.uid] => 1000
18`` ``[msg_perm.gid] => 1000
19`` ``[msg_perm.mode] => 438
20`` ``[msg_stime] => 1279849495
21`` ``[msg_rtime] => 0
22`` ``[msg_ctime] => 1279849495
23`` ``[msg_qnum] => 1
24`` ``[msg_qbytes] => 16384
25`` ``[msg_lspid] => 2184
26`` ``[msg_lrpid] => 0
27``)
28``Hello,World!
可以看到已成功从消息队列中读取“Hello,World!”字符串
下面列举一下示例代码中的主要函数:
01``ftok ( string $pathname , string $proj )
02`` ``手册上给出的解释是:Convert a pathname and a project identifier to a System V IPC key。这个函数返回的键值唯一对应linux系统中一个消息队列。在获得消息队列的引用之前都需要调用这个函数。
03
04``msg_get_queue ( int $key [, int $perms ] )
05`` ``msg_get_queue()会根据传入的键值返回一个消息队列的引用。如果linux系统中没有消息队列与键值对应,msg_get_queue()将会创建一个新的消息队列。函数的第二个参数需要传入一个int值,作为新创建的消息队列的权限值,默认为0666。这个权限值与linux命令 chmod 中使用的数值是同一个意思,因为在linux系统中一切皆是文件。
06
07``msg_send ( resource $queue , int $msgtype , mixed $message [, bool $serialize [, bool $blocking [, int & $errorcode ]]] )
08`` ``顾名思义,该函数用来向消息队列中写数据。
09
10``msg_stat_queue ( resource $queue )
11`` ``这个函数会返回消息队列的元数据。消息队列元数据中的信息很完整,包括了消息队列中待读取的消息数、最后读写队列的进程ID等。示例代码在第8行调用该函数返回的数组中队列中待读取的消息数msg_qnum值为0。
12
13``msg_receive ( resource $queue , int $desiredmsgtype , int & $msgtype , int $maxsize , mixed & $message [, bool $unserialize [, int $flags [, int & $errorcode ]]] )
14`` ``msg_receive用于读取消息队列中的数据。
15
16``msg_remove_queue ( resource $queue )
17`` ``msg_remove_queue用于销毁一个队列。
示例代码_1只是展示了PHP操作消息队列函数的应用。下面的代码具体描述了进程间通信的场景
01``<?php
02
03``$message_queue_key = ftok ( __FILE__ , 'a' );
04``$message_queue = msg_get_queue( $message_queue_key , 0666);
05
06``$pids = array ();
07``for ( $i = 0; $i < 5; $i ++) {
08`` ``//创建子进程
09`` ``$pids [ $i ] = pcntl_fork();
10
11`` ``if ( $pids [ $i ]) {
12`` ``echo "No.$i child process was created, the pid is $pids[$i]rn" ;
13`` ``} elseif ( $pids [ $i ] == 0) {
14`` ``$pid = posix_getpid();
15`` ``echo "process.$pid is writing nowrn" ;
16
17`` ``msg_send( $message_queue , 1, "this is process.$pid's datarn" );
18`` ``posix_kill( $pid , SIGTERM);
19`` ``}
20``}
21
22``do {
23`` ``msg_receive( $message_queue , 0, $message_type , 1024, $message , true, MSG_IPC_NOWAIT);
24`` ``echo $message ;
25
26`` ``//需要判断队列是否为空,如果为空就退出
27`` ``//break;
28``} while (true)
29
30``?>
运行结果为:
01``No.0 child process was created, the pid is 5249
02``No.1 child process was created, the pid is 5250
03``No.2 child process was created, the pid is 5251
04``No.3 child process was created, the pid is 5252
05``No.4 child process was created, the pid is 5253
06``process.5251 is writing now
07``this is process.5251's data
08``process.5253 is writing now
09``process.5252 is writing now
10``process.5250 is writing now
11``this is process.5253's data
12``this is process.5252's data
13``this is process.5250's data
14``process.5249 is writing now
15``this is process.5249's data
这段程序每次的运行结果都会不同,这正说明了多进程的异步性。从结果也能看出消息队列FIFO特性。
以上便是我研究的一点心得。接下来将会继续研究PHP利用信号、socket等进行进程间通信的方法。
来源: