# 管道( 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