利用PHP操作Linux消息队列完成进程间通信
By 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等进行进程间通信的方法。
来源: