当我们开发的系统需要使用多进程方式运行时,进程间通信便成了至关重要的环节。消息队列(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:
03 |
$message_queue_key = ftok ( __FILE__ , 'a' ); |
05 |
$message_queue = msg_get_queue( $message_queue_key , 0666); |
06 |
var_dump( $message_queue ); |
08 |
$message_queue_status = msg_stat_queue( $message_queue ); |
09 |
print_r( $message_queue_status ); |
12 |
msg_send( $message_queue , 1, "Hello,World!" ); |
14 |
$message_queue_status = msg_stat_queue( $message_queue ); |
15 |
print_r( $message_queue_status ); |
18 |
msg_receive( $message_queue , 0, $message_type , 1024, $message , true, MSG_IPC_NOWAIT); |
19 |
print_r( $message . "rn" ); |
21 |
msg_remove_queue( $message_queue ); |
这段代码的运行结果如下:
01 |
resource(4) of type (sysvmsg queue) |
04 |
[msg_perm.uid] => 1000 |
05 |
[msg_perm.gid] => 1000 |
06 |
[msg_perm.mode] => 438 |
09 |
[msg_ctime] => 1279849495 |
17 |
[msg_perm.uid] => 1000 |
18 |
[msg_perm.gid] => 1000 |
19 |
[msg_perm.mode] => 438 |
20 |
[msg_stime] => 1279849495 |
22 |
[msg_ctime] => 1279849495 |
可以看到已成功从消息队列中读取“Hello,World!”字符串
下面列举一下示例代码中的主要函数:
01 |
ftok ( string $pathname , string $proj ) |
02 |
手册上给出的解释是:Convert a pathname and a project identifier to a System V IPC key。这个函数返回的键值唯一对应linux系统中一个消息队列。在获得消息队列的引用之前都需要调用这个函数。 |
04 |
msg_get_queue ( int $key [, int $perms ] ) |
05 |
msg_get_queue()会根据传入的键值返回一个消息队列的引用。如果linux系统中没有消息队列与键值对应,msg_get_queue()将会创建一个新的消息队列。函数的第二个参数需要传入一个int值,作为新创建的消息队列的权限值,默认为0666。这个权限值与linux命令 chmod 中使用的数值是同一个意思,因为在linux系统中一切皆是文件。 |
07 |
msg_send ( resource $queue , int $msgtype , mixed $message [, bool $serialize [, bool $blocking [, int & $errorcode ]]] ) |
10 |
msg_stat_queue ( resource $queue ) |
11 |
这个函数会返回消息队列的元数据。消息队列元数据中的信息很完整,包括了消息队列中待读取的消息数、最后读写队列的进程ID等。示例代码在第8行调用该函数返回的数组中队列中待读取的消息数msg_qnum值为0。 |
13 |
msg_receive ( resource $queue , int $desiredmsgtype , int & $msgtype , int $maxsize , mixed & $message [, bool $unserialize [, int $flags [, int & $errorcode ]]] ) |
14 |
msg_receive用于读取消息队列中的数据。 |
16 |
msg_remove_queue ( resource $queue ) |
17 |
msg_remove_queue用于销毁一个队列。 |
示例代码_1只是展示了PHP操作消息队列函数的应用。下面的代码具体描述了进程间通信的场景
03 |
$message_queue_key = ftok ( __FILE__ , 'a' ); |
04 |
$message_queue = msg_get_queue( $message_queue_key , 0666); |
07 |
for ( $i = 0; $i < 5; $i ++) { |
09 |
$pids [ $i ] = pcntl_fork(); |
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" ; |
17 |
msg_send( $message_queue , 1, "this is process.$pid's datarn" ); |
18 |
posix_kill( $pid , SIGTERM); |
23 |
msg_receive( $message_queue , 0, $message_type , 1024, $message , true, MSG_IPC_NOWAIT); |
运行结果为:
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等进行进程间通信的方法。
来源:http://www.cnblogs.com/TechZi/archive/2010/07/23/1783342.html