写了一段代码,展示了PHP如何使用内核队列。
场景是:父进程产生消息,放入队列,子进程从队列读取消息,并处理。
<?php
$msg_key = ftok(__FILE__, 'a');
$msg_queue = msg_get_queue($msg_key, 0644);
/**
* 父进程往队列发送消息
* @param $msg_queue
* @param $child_count
*/
function parent_main($msg_queue, $child_count) {
// 发送100个消息
for ($j = 0; $j !== 100; $j++) {
msg_send($msg_queue, 1, 'hello ' . $j);
}
// 等待所有子进程退出
for ($j = 0; $j !== $child_count; $j++) {
pcntl_wait($status);
}
// 删除队列
msg_remove_queue($msg_queue);
}
/**
* 子进程从队列获取消息
* @param $msg_queue
*/
function child_main($msg_queue) {
// 刚启动时先睡一会儿,否则会因为读到的是空队列而直接退出
usleep(100000);
while (true) {
$ret = msg_receive($msg_queue, 0, $message_type,
1024, $message, true, MSG_IPC_NOWAIT);
// 如果没有消息可读了,就退出
if (!$ret) {
break;
}
echo 'Child ' . posix_getpid() . ' receive message: ' . $message . PHP_EOL;
}
}
$child_count = 4;
for ($i = 0; $i !== $child_count; $i++) {
$pid = pcntl_fork();
if ($pid === -1) {
die('Fork error');
} else if ($pid === 0) {
child_main($msg_queue);
exit(0);
}
}
parent_main($msg_queue, $child_count);
如果在程序退出前忘记删除队列了,可以用 ipcs
命令查看当前系统中的队列:
------ Message Queues --------
key msqid owner perms used-bytes messages
0x6d01e8f6 0 root 666 0 0
0x6d01e8f5 32769 root 666 0 0
0x6d01e8f4 65538 root 666 0 0
0x310164c6 98307 root 644 50 2
记住 msqid 这一列,这是队列ID,然后用 ipcrm
命令就可以删除不用的队列:
ipcrm -q 队列ID