进程通讯

几种进程通讯方式

# 管道( pipe ):管道是一种半双工的通讯方式,数据只能单向流动,并且只能在具备亲缘关系的进程间使用。进程的亲缘关系一般是指父子进程关系。
# 有名管道 (named pipe) : 有名管道也是半双工的通讯方式,可是它容许无亲缘关系进程间的通讯。
# 信号量( semophore ) : 信号量是一个计数器,能够用来控制多个进程对共享资源的访问。它常做为一种锁机制,防止某进程正在访问共享资源时,其余进程也访问该资源。所以,主要做为进程间以及同一进程内不一样线程之间的同步手段。
# 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
# 信号 ( sinal ) : 信号是一种比较复杂的通讯方式,用于通知接收进程某个事件已经发生。
# 共享内存( shared memory ) :共享内存就是映射一段能被其余进程所访问的内存,这段共享内存由一个进程建立,但多个进程均可以访问。共享内存是最快的 IPC 方式,它是针对其余进程间通讯方式运行效率低而专门设计的。它每每与其余通讯机制,如信号两,配合使用,来实现进程间的同步和通讯。
# 套接字( socket ) : 套解口也是一种进程间通讯机制,与其余通讯机制不一样的是,它可用于不一样及其间的进程通讯。php

 

PHP 消息队列linux

实际上,在PHP开发过程当中,对于消息队列的应用仍是很普遍的。消息队列(message queue)也是Linux系统进程间通讯的一种方式。
除了现有的一些消息队列解决方案之外,PHP对共享内存段的操做有两组函数:System V IPC和Shared Memory。 其中System V IPC由AT&T的贝尔实验室对早期的UNIX系统贡献而来,如今的linux系统都完美的继承了下来,该系列函数可以更方便的操做数据,无需像Shared Memory那样必须本身掌握读写时的偏移量、长度等,也不用序列化/反序列化来回转换(由于Shared Memory函数只支持字符串格式的数据参数)。可是System V IPC系列不支持Windows,因此若是要在win环境下使用,只能选Shared Memory。
PHP的System V msg模块是对Linux系统支持的System V IPC中的System V消息队列函数族的封装。咱们须要利用sysvmsg模块提供的函数来进进程间通讯。
 socket

<?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);
?>


因为System V IPC只支持linux类操做系统,以上演示请在linux中进行.
ftok函数将一个可访问的文件路径名转换为一个可供 shmop_open() 和其余系统VIPC keys使用的整数,proj参数必须是一个字符串,这个参数其实就是读写方式.
msg_get_queue()会根据传入的键值返回一个消息队列的引用。若是linux系统中没有消息队列与键值对应,msg_get_queue()将会建立一个新的消息队列。函数的第二个参数须要传入一个int值,做为新建立的消息队列的权限值,默认为0666。这个权限值与linux命令chmod中使用的数值是同一个意思,由于在linux系统中一切皆是文件。
msg_remove_queue用于销毁一个队列。
下面是子进程和主进程通讯:函数

<?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";
                pcntl_wait($status);//非阻塞的线程等待,防止僵尸进程的出现
        } 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;
        $a = msg_stat_queue($message_queue);
        if($a['msg_qnum'] == 0){
            break;
        }
} while(true)
 
?>


 
运行结果:
No.0 child process was created, the pid is 2196
process.2196 is writing now
No.1 child process was created, the pid is 2197
process.2197 is writing now
No.2 child process was created, the pid is 2198
process.2198 is writing now
No.3 child process was created, the pid is 2199
process.2199 is writing now
No.4 child process was created, the pid is 2200
process.2200 is writing now
this is process.2196's data
this is process.2197's data
this is process.2198's data
this is process.2199's data
this is process.2200's data
 
若是是验证父子进程间的通讯,能够这样作:
<?php
$message_queue_key = ftok(__FILE__, 'a');
$message_queue = msg_get_queue($message_queue_key, 0666);
$pid = pcntl_fork();
if ($pid==-1) {
        die("cannot fork");
} else if ($pid) {
                pcntl_wait($status);
                msg_receive($message_queue, 0, $message_type, 1024, $message, true, MSG_IPC_NOWAIT);
                echo $message;

} else {
        $pid = posix_getpid();

        msg_send($message_queue, 1, "this is process.$pid's data\r\n");
}
?>this

相关文章
相关标签/搜索